Documentation Index
Fetch the complete documentation index at: https://hastekit.ai/docs/llms.txt
Use this file to discover all available pages before exploring further.
Durable agent execution ensures that your agents can survive process crashes, restarts, or failures without losing progress. Using Restate, each step of the agent’s execution (LLM calls, tool executions) is checkpointed, allowing the agent to resume from exactly where it left off after a failure.
Why Durable Execution?
Traditional agents run in-memory. If your process crashes during:
- A long-running LLM call
- An external API request in a tool
- A multi-step conversation with many tool calls
…all progress is lost, and the entire execution must restart from scratch.
With durable execution:
- Checkpoint Every Step: Each LLM call and tool execution is automatically saved
- Automatic Recovery: After a crash, the agent resumes from the last checkpoint
- Exactly-Once Guarantees: Tool executions are never duplicated, even after retries
- Long-Running Workflows: Agents can run for hours or days without risk
Prerequisites
- Restate Server: You need a running Restate server. Follow the Restate installation guide to set one up.
Creating a Durable Agent
To create a durable agent, use NewRestateAgent() instead of NewAgent():
package main
import (
"log"
"net/http"
"os"
"github.com/hastekit/hastekit-sdk-go/pkg/gateway"
"github.com/hastekit/hastekit-sdk-go/pkg/gateway/llm"
hastekit "github.com/hastekit/hastekit-sdk-go"
)
func main() {
// Initialize SDK with Restate configuration
client, err := hastekit.New(&hastekit.ClientOptions{
ProviderConfigs: []gateway.ProviderConfig{
{
ProviderName: llm.ProviderNameOpenAI,
BaseURL: "",
CustomHeaders: nil,
ApiKeys: []*gateway.APIKeyConfig{
{
Name: "Key 1",
APIKey: os.Getenv("OPENAI_API_KEY"),
},
},
},
},
RestateConfig: hastekit.RestateConfig{
Endpoint: "http://localhost:8081", // Restate server endpoint
},
})
if err != nil {
log.Fatal(err)
}
model := client.NewLLM(hastekit.LLMOptions{
Provider: llm.ProviderNameOpenAI,
Model: "gpt-4o-mini",
})
// Create a durable agent with NewRestateAgent
agentName := "SampleAgent"
agent := client.NewRestateAgent(&hastekit.AgentOptions{
Name: agentName,
Instruction: client.Prompt("You are helpful assistant."),
LLM: model,
History: client.NewConversationManager(),
})
}
Deployment Options
There are two ways to deploy durable agents:
Option 1: Single Process (Development/Testing)
Run both the Restate service handler and the application code in the same process. This is simpler but less resilient since both components share the same process lifecycle.
func main() {
// ... client and agent setup from above ...
// Start Restate service in a goroutine
client.StartRestateService("0.0.0.0", "9081")
// Start HTTP server for invoking the workflow
http.ListenAndServe(":8070", client)
}
With this setup:
- The Restate service runs on
http://localhost:9080
- Your application server runs on
http://localhost:8070
- Both are in the same process
Note: If this process crashes, both components restart together. True durability requires separation (Option 2).
Option 2: Separate Processes (Production)
For production deployments, run the Restate service and application in separate processes. This provides true fault isolation—if your application crashes, the Restate service continues running and can recover the workflow.
Application Process
// application/main.go
package main
import (
"context"
"log"
"net/http"
"os"
"github.com/hastekit/hastekit-sdk-go/pkg/agents"
"github.com/hastekit/hastekit-sdk-go/pkg/agents/prompts""
"github.com/hastekit/hastekit-sdk-go/pkg/gateway"
"github.com/hastekit/hastekit-sdk-go/pkg/gateway/llm"
"github.com/hastekit/hastekit-sdk-go/pkg/gateway/llm/responses"
hastekit "github.com/hastekit/hastekit-sdk-go"
)
func main() {
client, err := hastekit.New(&hastekit.ClientOptions{
ProviderConfigs: []gateway.ProviderConfig{
{
ProviderName: llm.ProviderNameOpenAI,
BaseURL: "",
CustomHeaders: nil,
ApiKeys: []*gateway.APIKeyConfig{
{
Name: "Key 1",
APIKey: os.Getenv("OPENAI_API_KEY"),
},
},
},
},
RestateConfig: hastekit.RestateConfig{
Endpoint: "http://localhost:8081", // Restate server
},
})
if err != nil {
log.Fatal(err)
}
model := client.NewLLM(hastekit.LLMOptions{
Provider: llm.ProviderNameOpenAI,
Model: "gpt-4o-mini",
})
// Register the agent
agentName := "my-agent"
_ = client.NewRestateAgent(&hastekit.AgentOptions{
Name: agentName,
Instruction: client.Prompt("You are a helpful assistant."),
LLM: model,
History: client.NewConversationManager(),
})
// Start application server
log.Println("Application server starting on :8070")
http.ListenAndServe(":8070", client)
}
Restate Service Process
// restate-service/main.go
package main
import (
"log"
"os"
"github.com/hastekit/hastekit-sdk-go/pkg/agents/prompts""
"github.com/hastekit/hastekit-sdk-go/pkg/gateway"
"github.com/hastekit/hastekit-sdk-go/pkg/gateway/llm"
hastekit "github.com/hastekit/hastekit-sdk-go"
)
func main() {
client, err := hastekit.New(&hastekit.ClientOptions{
ProviderConfigs: []gateway.ProviderConfig{
{
ProviderName: llm.ProviderNameOpenAI,
BaseURL: "",
CustomHeaders: nil,
ApiKeys: []*gateway.APIKeyConfig{
{
Name: "Key 1",
APIKey: os.Getenv("OPENAI_API_KEY"),
},
},
},
},
RestateConfig: hastekit.RestateConfig{
Endpoint: "http://localhost:8081",
},
})
if err != nil {
log.Fatal(err)
}
model := client.NewLLM(hastekit.LLMOptions{
Provider: llm.ProviderNameOpenAI,
Model: "gpt-4o-mini",
})
// Register the SAME agent with the SAME configuration
agentName := "my-agent"
_ = client.NewRestateAgent(&hastekit.AgentOptions{
Name: agentName,
Instruction: client.Prompt("You are a helpful assistant."),
LLM: model,
History: client.NewConversationManager(),
})
// Start only the Restate service
log.Println("Restate service starting on :9081")
client.StartRestateService("0.0.0.0", "9081")
}
Important: Both processes must register the agent with the exact same name and configuration. This ensures the Restate service can execute the agent with the correct setup.
Running the Services
# Terminal 1: Start the Restate service
cd restate-service
go run main.go
# Terminal 2: Start the application
cd application
go run main.go
Registering the Deployment with Restate Server
After starting your Restate service (on port 9081), you must register it with the Restate server so it can discover and invoke your agent workflows.
Using the Restate CLI
# Install Restate CLI (if not already installed)
npm install -g @restatedev/restate
# Register the deployment
restate deployments register http://localhost:9081
Using the Admin API
curl localhost:9070/deployments --json '{"uri": "http://localhost:9081"}'
Using the Restate UI
Navigate to your Restate server’s UI (typically http://localhost:9070) and register the deployment through the web interface.
Note: If running Restate in Docker, replace localhost with host.docker.internal:
restate deployments register http://host.docker.internal:9081
Automatic Registration
For production environments, consider automating deployment registration:
- Kubernetes: Use the Restate Kubernetes Operator for automatic registration and lifecycle management
- CI/CD Pipeline: Add deployment registration as a step in your CI/CD pipeline
- FaaS Platforms: AWS Lambda, Vercel, and other FaaS platforms automatically handle versioning through version-specific ARNs/URLs
See the Restate deployment documentation for more details.
Example: Complete Durable Agent
See the complete working example in the repository: examples/agents/8_restate_agent/main.go
Learn More