This guide walks you through installing Minion and creating your first AI agent.
- Go 1.24+ - Download Go
- LLM API key - OpenAI, Anthropic, or local Ollama
go get github.com/Ranganaths/minionmkdir myagent && cd myagent
go mod init myagent
go get github.com/Ranganaths/minion# OpenAI
export OPENAI_API_KEY="sk-..."
# Or Anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
# Or use local Ollama (no key needed)
ollama serveCreate main.go:
package main
import (
"context"
"fmt"
"os"
"github.com/Ranganaths/minion/core"
"github.com/Ranganaths/minion/llm"
"github.com/Ranganaths/minion/models"
"github.com/Ranganaths/minion/storage"
)
func main() {
// Create framework
framework := core.NewFramework(
core.WithStorage(storage.NewInMemory()),
core.WithLLMProvider(llm.NewOpenAI(os.Getenv("OPENAI_API_KEY"))),
)
defer framework.Close()
// Create agent
ctx := context.Background()
agent, _ := framework.CreateAgent(ctx, &models.CreateAgentRequest{
Name: "Assistant",
Description: "A helpful AI assistant",
})
// Activate agent
activeStatus := models.StatusActive
framework.UpdateAgent(ctx, agent.ID, &models.UpdateAgentRequest{
Status: &activeStatus,
})
// Execute
output, _ := framework.Execute(ctx, agent.ID, &models.Input{
Raw: "What is the capital of France?",
})
fmt.Println(output.Result)
}go run main.go
# Output: Paris is the capital of France.The Framework is the central component that manages agents, tools, and execution:
framework := core.NewFramework(
core.WithStorage(storage.NewInMemory()), // Storage backend
core.WithLLMProvider(llm.NewOpenAI(apiKey)), // LLM provider
core.WithToolRegistry(tools.NewRegistry()), // Tool registry
)
defer framework.Close()Agents are AI entities with configurable behavior:
agent, err := framework.CreateAgent(ctx, &models.CreateAgentRequest{
Name: "Analyst",
Description: "A data analysis agent",
BehaviorType: "default", // Or "react" for ReAct reasoning
Config: models.AgentConfig{
LLMProvider: "openai",
LLMModel: "gpt-4",
Temperature: 0.7,
MaxTokens: 2048,
},
Capabilities: []string{"data_analysis", "visualization"},
})Agent Status:
draft- Initial state, not executableactive- Ready for executioninactive- Temporarily disabledarchived- Soft deleted
Execute an agent with input:
output, err := framework.Execute(ctx, agent.ID, &models.Input{
Raw: "Analyze this data...",
Type: "text",
Context: map[string]interface{}{
"data": myData,
},
})
fmt.Println(output.Result)
fmt.Println(output.Metadata["tokens_used"])Agents can use tools to perform actions:
// Register a custom tool
framework.RegisterTool(&MyCustomTool{})
// Execute a tool
output, err := framework.ExecuteTool(ctx, "my_tool", map[string]interface{}{
"param1": "value1",
})Switch between providers:
// OpenAI
provider := llm.NewOpenAI(os.Getenv("OPENAI_API_KEY"))
// Anthropic
provider := llm.NewAnthropic(os.Getenv("ANTHROPIC_API_KEY"))
// Ollama (local)
provider := llm.NewOllama("http://localhost:11434")
// With tool support
provider := llm.NewOpenAIWithTools(os.Getenv("OPENAI_API_KEY"))package main
import (
"context"
"fmt"
"os"
"github.com/Ranganaths/minion/core"
"github.com/Ranganaths/minion/llm"
"github.com/Ranganaths/minion/models"
"github.com/Ranganaths/minion/storage"
)
func main() {
// Create framework with tool-enabled provider
framework := core.NewFramework(
core.WithStorage(storage.NewInMemory()),
core.WithLLMProvider(llm.NewOpenAIWithTools(os.Getenv("OPENAI_API_KEY"))),
)
defer framework.Close()
ctx := context.Background()
// Create agent with tool capabilities
agent, _ := framework.CreateAgent(ctx, &models.CreateAgentRequest{
Name: "Tool Agent",
Description: "An agent that uses tools",
Capabilities: []string{"file_operations", "web"},
})
// List available tools
tools := framework.GetToolsForAgent(agent)
fmt.Printf("Available tools: %d\n", len(tools))
// Execute tool directly
output, _ := framework.ExecuteTool(ctx, "http_get", map[string]interface{}{
"url": "https://api.example.com/data",
})
fmt.Println(output.Result)
}Connect external tools via Model Context Protocol:
package main
import (
"context"
"os"
"github.com/Ranganaths/minion/core"
"github.com/Ranganaths/minion/llm"
"github.com/Ranganaths/minion/mcp/client"
"github.com/Ranganaths/minion/storage"
)
func main() {
framework := core.NewFramework(
core.WithStorage(storage.NewInMemory()),
core.WithLLMProvider(llm.NewOpenAI(os.Getenv("OPENAI_API_KEY"))),
)
defer framework.Close()
ctx := context.Background()
// Connect to MCP server (e.g., GitHub tools)
framework.ConnectMCPServer(ctx, &client.ClientConfig{
ServerName: "github",
Command: "npx",
Args: []string{"-y", "@modelcontextprotocol/server-github"},
Env: map[string]string{
"GITHUB_TOKEN": os.Getenv("GITHUB_TOKEN"),
},
})
// MCP tools are now available
tools := framework.ListTools()
for _, name := range tools {
if name[:7] == "github_" {
fmt.Println(name)
}
}
}package main
import (
"context"
"os"
"github.com/Ranganaths/minion/agents/multiagent"
"github.com/Ranganaths/minion/agents/workers"
"github.com/Ranganaths/minion/llm"
)
func main() {
provider := llm.NewOpenAI(os.Getenv("OPENAI_API_KEY"))
// Create orchestrator
orchestrator := multiagent.NewOrchestrator(provider)
// Create coordinator with specialized workers
coordinator := multiagent.NewCoordinator(
multiagent.WithOrchestrator(orchestrator),
multiagent.WithWorkers(
workers.NewCoderWorker(provider),
workers.NewAnalystWorker(provider),
workers.NewResearcherWorker(provider),
),
)
// Execute complex task
ctx := context.Background()
result, _ := coordinator.Execute(ctx, "Build a REST API for user management")
fmt.Println(result)
}Expose your agent via A2A or AG-UI protocol:
// A2A Server (Agent-to-Agent)
package main
import (
"log"
"github.com/Ranganaths/minion/protocols/a2a"
)
func main() {
// ... create framework and agent ...
config := a2a.DefaultServerConfig()
server, _ := a2a.NewA2AServer(framework, agent.ID, "http://localhost:8080", config)
log.Println("A2A server at http://localhost:8080")
log.Println("Agent card: http://localhost:8080/.well-known/agent.json")
log.Fatal(server.ListenAndServe(":8080"))
}// AG-UI Server (for frontend streaming)
package main
import (
"log"
"github.com/Ranganaths/minion/protocols/agui"
)
func main() {
// ... create framework and agent ...
config := agui.DefaultServerConfig()
config.EnableCORS = true
server, _ := agui.NewAGUIServer(framework, agent.ID, config)
log.Println("AG-UI server at http://localhost:8081")
log.Fatal(server.ListenAndServe(":8081"))
}agent, _ := framework.CreateAgent(ctx, &models.CreateAgentRequest{
Name: "My Agent",
Description: "Agent description",
BehaviorType: "default", // or "react"
Config: models.AgentConfig{
LLMProvider: "openai",
LLMModel: "gpt-4",
Temperature: 0.7, // 0.0-1.0 creativity
MaxTokens: 2048, // Max response tokens
Personality: "professional",
Language: "en",
Custom: map[string]interface{}{
"custom_setting": "value",
},
},
Capabilities: []string{
"file_operations",
"web",
"data_analysis",
},
Metadata: map[string]interface{}{
"team": "engineering",
"version": "1.0",
},
})// In-Memory (development)
store := storage.NewInMemory()
// PostgreSQL (production)
store, _ := storage.NewPostgreSQL(storage.PostgreSQLConfig{
Host: "localhost",
Port: 5432,
User: "minion",
Password: "password",
Database: "minion",
})import (
"github.com/Ranganaths/minion/observability"
"github.com/Ranganaths/minion/metrics"
)
// Enable tracing
observability.InitTracer(observability.Config{
ServiceName: "my-agent",
Endpoint: "http://localhost:4318", // OTLP endpoint
})
// Enable metrics
metrics.InitMetrics(metrics.Config{
Endpoint: ":9090", // Prometheus endpoint
})output, err := framework.Execute(ctx, agent.ID, input)
if err != nil {
// Framework-level error
switch {
case errors.Is(err, storage.ErrNotFound):
log.Println("Agent not found")
case errors.Is(err, llm.ErrRateLimit):
log.Println("Rate limited, retry later")
default:
log.Printf("Execution error: %v", err)
}
return
}
// Check metadata for warnings
if output.Metadata != nil {
if warning, ok := output.Metadata["warning"]; ok {
log.Printf("Warning: %v", warning)
}
}- Always close the framework - Use
defer framework.Close() - Use contexts - Pass context for cancellation and tracing
- Handle errors - Check both execution errors and output metadata
- Limit capabilities - Give agents only needed permissions
- Configure timeouts - Set appropriate LLM timeouts
- Use structured logging - Log agent IDs and trace IDs
- Architecture - Deep dive into system design
- API Reference - Complete API documentation
- Protocols - A2A, AG-UI, MCP integration
- Examples - More code examples
// Add storage to framework
framework := core.NewFramework(
core.WithStorage(storage.NewInMemory()),
// ...
)// Add LLM provider
framework := core.NewFramework(
core.WithLLMProvider(llm.NewOpenAI(apiKey)),
// ...
)// Activate the agent
activeStatus := models.StatusActive
framework.UpdateAgent(ctx, agent.ID, &models.UpdateAgentRequest{
Status: &activeStatus,
})// Use "default" or register custom behavior
agent, _ := framework.CreateAgent(ctx, &models.CreateAgentRequest{
BehaviorType: "default", // Built-in behavior
// ...
})