Local Development¶
AgentKit is designed for seamless local development. The same code runs locally and in production - only the infrastructure differs.
Running Locally¶
HTTP Server¶
Test your endpoints:
# Health check
curl http://localhost:8001/health
# Your endpoint
curl -X POST http://localhost:8001/research \
-H "Content-Type: application/json" \
-d '{"query": "test"}'
A2A Server¶
Test the A2A endpoints:
# Agent card
curl http://localhost:9001/.well-known/agent.json
# Invoke
curl -X POST http://localhost:9001/invoke \
-H "Content-Type: application/json" \
-d '{"method": "agent/run", "params": {"prompt": "test"}}'
AgentCore Runtime¶
The AgentCore server runs locally with the same /ping and /invocations endpoints as production:
Test the endpoints:
# Health check
curl http://localhost:8080/ping
# Invoke agent
curl -X POST http://localhost:8080/invocations \
-H "Content-Type: application/json" \
-d '{"prompt": "Find statistics about AI adoption"}'
Local vs Production¶
The code is identical - only the infrastructure changes:
| Aspect | Local | Kubernetes | AWS AgentCore |
|---|---|---|---|
| Process | Go binary | Container | Firecracker microVM |
| Sessions | In-memory | Pod-based | Isolated per microVM |
| Scaling | Manual | HPA | Automatic |
| Startup | Instant | Container pull | Cold start ~100ms |
Environment Setup¶
Create a .env file for local development:
# LLM Provider
LLM_PROVIDER=gemini
GEMINI_API_KEY=your-api-key
# Optional: Observability
OBSERVABILITY_ENABLED=false
# Optional: Search provider
SEARCH_PROVIDER=serper
SERPER_API_KEY=your-api-key
Load it:
Or use a tool like direnv.
Hot Reload¶
For faster development iteration, use a tool like air:
Create .air.toml:
[build]
cmd = "go build -o ./tmp/main ."
bin = "./tmp/main"
include_ext = ["go"]
exclude_dir = ["tmp", "vendor"]
Testing¶
Unit Tests¶
Integration Tests¶
Test your agent endpoints:
func TestResearchEndpoint(t *testing.T) {
// Start server
server, _ := httpserver.NewBuilder("test-agent", 0). // Port 0 = random
WithHandlerFunc("/research", agent.HandleResearch).
Build()
server.StartAsync()
defer server.Stop(context.Background())
// Make request
resp, err := http.Post(
server.URL()+"/research",
"application/json",
strings.NewReader(`{"query": "test"}`),
)
// Assert
assert.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
}
A2A Server Testing¶
func TestA2AServer(t *testing.T) {
server, _ := a2a.NewServer(a2a.Config{
Agent: myAgent,
Port: "", // Random port
})
server.StartAsync(context.Background())
defer server.Stop(context.Background())
// Fetch agent card
resp, _ := http.Get(server.AgentCardURL())
assert.Equal(t, 200, resp.StatusCode)
}
Debugging¶
Enable Request Logging¶
server, _ := httpserver.NewBuilder("my-agent", 8001).
WithHandlerFunc("/research", agent.HandleResearch).
WithDualModeLog(). // Logs startup info
Build()
Verbose LLM Logging¶
Set the log level: