2026-03-04 07:33:19 +00:00
---
layout: default
---
# Agent Integration Patterns
This guide covers common patterns for integrating AI agents with Go Micro services, from single-agent workflows to multi-agent architectures.
## Pattern 1: Single Agent with Multiple Services
The simplest and most common pattern. One AI agent has access to multiple microservices as MCP tools.
```
User → AI Agent → MCP Gateway → [Service A, Service B, Service C]
```
### Setup
Run multiple services and expose them all through one MCP gateway:
```go
2026-06-18 11:55:35 +01:00
users := micro . NewService ( "users" , micro . Address ( ":8081" ))
tasks := micro . NewService ( "tasks" , micro . Address ( ":8082" ))
notifications := micro . NewService ( "notifications" , micro . Address ( ":8083" ))
2026-03-04 07:33:19 +00:00
2026-03-04 11:13:27 +00:00
// Run all together as a modular monolith
g := micro . NewGroup ( users , tasks , notifications )
g . Run ()
2026-03-04 07:33:19 +00:00
```
2026-05-26 12:19:26 +01:00
With `micro run` , all services are discovered automatically via the registry, and the MCP tools endpoint at `/mcp/tools` exposes every endpoint from every service.
2026-03-04 07:33:19 +00:00
### When to Use
- Most applications start here
- Agent needs to orchestrate across services (e.g., "create a task and notify the assignee")
- You want the agent to choose which service to call based on the user's request
## Pattern 2: Scoped Agents
Different agents have access to different subsets of tools via scopes.
```
Customer Agent → MCP Gateway → [orders:read, support:write]
Internal Agent → MCP Gateway → [orders:*, users:*, billing:*]
Admin Agent → MCP Gateway → [*]
```
### Setup
Create tokens with different scopes for each agent:
```go
// Gateway with scope enforcement
mcp . ListenAndServe ( ":3000" , mcp . Options {
Registry : reg ,
Auth : authProvider ,
Scopes : map [ string ][] string {
"billing.Billing.Charge" : { "billing:admin" },
"users.Users.Delete" : { "users:admin" },
"orders.Orders.List" : { "orders:read" },
"orders.Orders.Create" : { "orders:write" },
"support.Support.CreateTicket" : { "support:write" },
},
})
```
Then issue different tokens:
- Customer-facing agent token: `scopes=["orders:read", "support:write"]`
- Internal agent token: `scopes=["orders:read", "orders:write", "users:read"]`
- Admin agent token: `scopes=["*"]`
### When to Use
- Different trust levels for different agents
- Customer-facing vs internal agents
- Compliance requirements (e.g., PCI, HIPAA)
## Pattern 3: Agent as Service Consumer
2026-03-04 13:13:34 +00:00
Your Go Micro service itself calls an AI model to process data, using the `ai` package.
2026-03-04 07:33:19 +00:00
```
User → API → Your Service → AI Model (Claude/GPT)
→ Other Services
```
### Setup
```go
import (
2026-06-18 11:55:35 +01:00
"go-micro.dev/v6/ai"
_ "go-micro.dev/v6/ai/anthropic"
2026-03-04 07:33:19 +00:00
)
type SummaryService struct {
2026-03-04 13:13:34 +00:00
ai ai . Model
2026-03-04 07:33:19 +00:00
tasks * TaskClient
}
func NewSummaryService () * SummaryService {
return & SummaryService {
2026-03-04 13:13:34 +00:00
ai : ai . New ( "anthropic" ,
ai . WithAPIKey ( os . Getenv ( "ANTHROPIC_API_KEY" )),
ai . WithModel ( "claude-sonnet-4-20250514" ),
2026-03-04 07:33:19 +00:00
),
}
}
// Summarize generates an AI summary of a project's tasks.
// Returns a natural language summary of task status, blockers, and progress.
//
// @example {"project_id": "proj-1"}
func ( s * SummaryService ) Summarize ( ctx context . Context , req * SummarizeRequest , rsp * SummarizeResponse ) error {
// Fetch tasks from another service
tasks , err := s . tasks . List ( ctx , req . ProjectID )
if err != nil {
return err
}
// Use AI to summarize
2026-03-04 13:13:34 +00:00
resp , err := s . ai . Generate ( ctx , & ai . Request {
2026-03-04 07:33:19 +00:00
Prompt : fmt . Sprintf ( "Summarize these tasks:\n%s" , formatTasks ( tasks )),
SystemPrompt : "You are a concise project manager. Summarize task status in 2-3 sentences." ,
})
if err != nil {
return err
}
rsp . Summary = resp . Reply
return nil
}
```
### When to Use
- Your service needs to process natural language
- Generating summaries, classifications, or extractions
- Enriching data with AI before returning to the caller
## Pattern 4: Agent with Tool Calling
2026-03-04 13:13:34 +00:00
An AI model calls your services as tools, with automatic tool execution via the ai package.
2026-03-04 07:33:19 +00:00
```
User → Your App → AI Model ←→ MCP Tools (your services)
```
### Setup
```go
import (
2026-06-18 11:55:35 +01:00
"go-micro.dev/v6/ai"
_ "go-micro.dev/v6/ai/anthropic"
2026-03-04 07:33:19 +00:00
)
// Define tools from your service endpoints
2026-03-04 13:13:34 +00:00
tools := [] ai . Tool {
2026-03-04 07:33:19 +00:00
{
Name : "create_task" ,
Description : "Create a new task with title and assignee" ,
Properties : map [ string ] any {
"title" : map [ string ] any { "type" : "string" , "description" : "Task title" },
"assignee" : map [ string ] any { "type" : "string" , "description" : "Username" },
},
},
{
Name : "list_tasks" ,
Description : "List tasks filtered by status" ,
Properties : map [ string ] any {
"status" : map [ string ] any { "type" : "string" , "description" : "Filter: todo, in_progress, done" },
},
},
}
2026-06-16 16:26:56 +01:00
// Handle tool calls by routing to your services. The handler mirrors a
// go-micro RPC handler: context first, the call in, a result out.
toolHandler := func ( ctx context . Context , call ai . ToolCall ) ai . ToolResult {
switch call . Name {
2026-03-04 07:33:19 +00:00
case "create_task" :
var rsp CreateResponse
2026-06-16 16:26:56 +01:00
err := client . Call ( ctx , "tasks" , "TaskService.Create" , call . Input , & rsp )
2026-03-04 07:33:19 +00:00
if err != nil {
2026-06-16 16:26:56 +01:00
return ai . ToolResult { ID : call . ID , Content : fmt . Sprintf ( `{"error": "%s"}` , err )}
2026-03-04 07:33:19 +00:00
}
b , _ := json . Marshal ( rsp )
2026-06-16 16:26:56 +01:00
return ai . ToolResult { ID : call . ID , Value : rsp , Content : string ( b )}
2026-03-04 07:33:19 +00:00
case "list_tasks" :
var rsp ListResponse
2026-06-16 16:26:56 +01:00
err := client . Call ( ctx , "tasks" , "TaskService.List" , call . Input , & rsp )
2026-03-04 07:33:19 +00:00
if err != nil {
2026-06-16 16:26:56 +01:00
return ai . ToolResult { ID : call . ID , Content : fmt . Sprintf ( `{"error": "%s"}` , err )}
2026-03-04 07:33:19 +00:00
}
b , _ := json . Marshal ( rsp )
2026-06-16 16:26:56 +01:00
return ai . ToolResult { ID : call . ID , Value : rsp , Content : string ( b )}
2026-03-04 07:33:19 +00:00
}
2026-06-16 16:26:56 +01:00
return ai . ToolResult { ID : call . ID , Content : `{"error": "unknown tool"}` }
2026-03-04 07:33:19 +00:00
}
2026-03-04 13:13:34 +00:00
m := ai . New ( "anthropic" ,
ai . WithAPIKey ( os . Getenv ( "ANTHROPIC_API_KEY" )),
ai . WithToolHandler ( toolHandler ),
2026-03-04 07:33:19 +00:00
)
// The model will automatically call tools and return the final answer
2026-03-04 13:13:34 +00:00
resp , err := m . Generate ( ctx , & ai . Request {
2026-03-04 07:33:19 +00:00
Prompt : "Create a task for Alice to review the PR and tell me what tasks she has" ,
SystemPrompt : "You are a helpful project management assistant" ,
Tools : tools ,
})
fmt . Println ( resp . Answer )
// "I've created a task for Alice to review the PR. She now has 3 tasks: ..."
```
### When to Use
- Building a chatbot or assistant that manages your services
- The agent playground in `micro run` uses this pattern
- You want the AI to decide which tools to call and in what order
## Pattern 5: Event-Driven Agent Triggers
Services emit events that trigger agent actions via the broker.
```
Service → Broker Event → Agent Handler → AI Model → Action
```
### Setup
```go
// Publisher: emit events from your service
broker . Publish ( "tasks.created" , & broker . Message {
Body : taskJSON ,
})
// Subscriber: agent handler reacts to events
broker . Subscribe ( "tasks.created" , func ( p broker . Event ) error {
var task Task
json . Unmarshal ( p . Message (). Body , & task )
// Use AI to auto-assign based on task content
2026-03-04 13:13:34 +00:00
resp , err := aiModel . Generate ( ctx , & ai . Request {
2026-03-04 07:33:19 +00:00
Prompt : fmt . Sprintf ( "Who should handle this task? Title: %s, Description: %s. Team: alice (frontend), bob (backend), charlie (devops)" , task . Title , task . Description ),
SystemPrompt : "Reply with just the username of the best person to handle this task." ,
})
// Auto-assign
client . Call ( ctx , "tasks" , "TaskService.Update" , map [ string ] any {
"id" : task . ID ,
"assignee" : strings . TrimSpace ( resp . Reply ),
}, nil )
return nil
})
```
### When to Use
- Automated workflows triggered by service events
- AI-powered routing, classification, or triage
- Background processing without user interaction
## Pattern 6: Claude Code Integration
Developers use Claude Code with your services as MCP tools for local development workflows.
```
Developer → Claude Code → stdio MCP → [local services]
```
### Setup
```bash
# Start services locally
micro run
# In another terminal, use Claude Code with your services
# Claude Code config (~/.claude/claude_desktop_config.json):
```
```json
{
"mcpServers" : {
"my-project" : {
"command" : "micro" ,
"args" : [ "mcp" , "serve" ]
}
}
}
```
Now in Claude Code:
```
"List all tasks that are blocked"
"Create a user account for the new hire"
"Check the health of all services"
```
### When to Use
- Developer productivity workflows
- Managing services during development
- Testing and debugging with natural language
2026-03-04 10:16:17 +00:00
## Pattern 7: LangChain / LlamaIndex Integration
Use the official Python SDKs to connect agent frameworks directly to your services.
### LangChain
```python
from langchain_go_micro import GoMicroToolkit
# Connect to MCP gateway
toolkit = GoMicroToolkit (
base_url = "http://localhost:3000" ,
token = "Bearer <token>" ,
)
# Get LangChain tools automatically
tools = toolkit . get_tools ()
# Use with any LangChain agent
from langchain.agents import AgentExecutor , create_tool_calling_agent
agent = create_tool_calling_agent ( llm , tools , prompt )
executor = AgentExecutor ( agent = agent , tools = tools )
executor . invoke ({ "input" : "Create a task for Alice" })
```
### LlamaIndex
```python
from go_micro_llamaindex import GoMicroToolkit
toolkit = GoMicroToolkit (
base_url = "http://localhost:3000" ,
token = "Bearer <token>" ,
)
# Use as LlamaIndex tools
tools = toolkit . to_tool_list ()
# Use with a LlamaIndex agent
from llama_index.core.agent import ReActAgent
agent = ReActAgent . from_tools ( tools , llm = llm )
agent . chat ( "What tasks are assigned to Bob?" )
```
### When to Use
- Python-based agent pipelines
- RAG (Retrieval-Augmented Generation) workflows with LlamaIndex
- Multi-step LangChain chains that orchestrate your services
- Teams that prefer Python for AI/ML work
## Pattern 8: Standalone Gateway for Production
Run the MCP gateway as a separate, horizontally scalable process.
```
┌──────────────────┐
Claude/GPT/Agent ──→│ micro-mcp-gateway │──→ Service A (consul)
│ (standalone) │──→ Service B (consul)
└──────────────────┘──→ Service C (consul)
```
### Setup
```bash
micro-mcp-gateway \
--registry consul \
--registry-address consul:8500 \
--address :3000 \
--auth jwt \
--rate-limit 10 \
--rate-burst 20 \
--audit
```
Or via Docker:
```bash
docker run -p 3000:3000 ghcr.io/micro/micro-mcp-gateway \
--registry consul \
--registry-address consul:8500
```
### When to Use
- Production deployments where you want the gateway to scale independently
- Multiple teams deploying services but sharing one MCP endpoint
- Enterprise environments needing centralized auth and audit
2026-06-07 10:55:34 +01:00
## Pattern 9: Planning and Delegation
2026-06-24 11:37:43 +01:00
Built into the `Agent` abstraction. Every agent gets two harness tools — `plan` and `delegate` — with no extra setup. They are plain tools, not a separate graph runtime.
2026-06-07 10:55:34 +01:00
```
2026-06-07 18:33:04 +01:00
Conductor ──plan──→ (records ordered steps in memory)
2026-06-07 10:55:34 +01:00
──delegate──→ registered agent (RPC) or ephemeral sub-agent
```
### Setup
Nothing to wire — the tools are added to every agent automatically. Guide their use with the prompt:
```go
2026-06-07 18:33:04 +01:00
conductor := micro . NewAgent ( "conductor" ,
2026-06-07 10:55:34 +01:00
micro . AgentServices ( "task" ),
micro . AgentPrompt (
"For multi-step requests, call the plan tool first to record your steps. " +
"For notifications, delegate to the \"comms\" agent (to: \"comms\")." ),
micro . AgentProvider ( "anthropic" ),
)
```
- **`plan` ** records an ordered list of steps (`task` + `status` ) in the agent's store-backed memory, surfaced back on later turns so it stays oriented.
- **`delegate` ** hands a self-contained subtask to another agent. **Delegate-first** : if the target is a registered agent it's reached over RPC; otherwise a focused, short-lived sub-agent is created with a fresh, isolated context. A sub-agent is just an agent — created with `New` , talked to with `Ask` ; there's no separate "spawn"/"fork" concept.
Full example: [examples/agent-plan-delegate ](https://github.com/micro/go-micro/tree/master/examples/agent-plan-delegate ).
### When to Use
- Multi-step tasks where an explicit plan keeps the agent on track
- Multi-agent systems where domain experts own their own services and you want hand-offs to stay distributed (not one agent doing everything)
2026-03-04 07:33:19 +00:00
## Choosing a Pattern
| Pattern | Complexity | Best For |
|---------|-----------|----------|
| Single Agent | Low | Most applications, getting started |
| Scoped Agents | Medium | Multi-tenant, compliance |
| Agent as Consumer | Medium | AI-enhanced services |
| Tool Calling | Medium | Chatbots, assistants |
| Event-Driven | High | Automation, background processing |
| Claude Code | Low | Developer workflows |
2026-03-04 10:16:17 +00:00
| LangChain/LlamaIndex | Medium | Python agent pipelines, RAG |
| Standalone Gateway | Medium | Production, enterprise |
2026-06-07 10:55:34 +01:00
| Planning & Delegation | Medium | Multi-step tasks, distributed multi-agent systems |
2026-03-04 07:33:19 +00:00
Start with **Pattern 1** (single agent) and add complexity as needed. Most applications don't need multi-agent architectures.
## Anti-Patterns
### Don't: Chain Agents Without Coordination
```
Agent A → Agent B → Agent C (no shared state, no trace IDs)
```
Instead, use a single agent with multiple tools, or share trace IDs via metadata.
### Don't: Give Agents Unrestricted Access
```
Customer Agent → scopes=["*"] (dangerous!)
```
Always use the minimum required scopes. See the [MCP Security Guide ](mcp-security.md ).
### Don't: Skip Error Documentation
If agents don't know what errors are possible, they can't handle them gracefully. Always document error cases in your handler comments.
### Don't: Build Agent Logic into Services
2026-06-24 11:37:43 +01:00
Keep services as pure business logic. Let the agent harness handle orchestration, retries, and decision-making. Your service should just do one thing well.
2026-03-04 07:33:19 +00:00
## Next Steps
- [Building AI-Native Services ](ai-native-services.md ) - End-to-end tutorial
- [MCP Security Guide ](mcp-security.md ) - Auth and scopes
- [Tool Description Best Practices ](tool-descriptions.md ) - Better docs for agents
2026-03-04 13:13:34 +00:00
- [AI Package ](../../ai/README.md ) - AI provider interface