* test(harness): read agent plan from the scoped store
The store-scoping change moved an agent's plan from the default table
key agent/{name}/plan to its own table (database "agent", table {name},
key "plan"). The plan-delegate harness tests still read the old key and
failed with 'not found'; read through store.Scope(mem, "agent", name)
like the agent does.
* docs: orient agents-first across README, landing, and docs overview
Lead with agents (then services and flows), surface MCP + A2A as the
interop story, and frame agents as services. Landing hero and feature
grid reordered agents-first with an A2A gateway card.
* v6: module path go-micro.dev/v6, TLS secure by default, NewService
Cut v6. Three breaking changes, bundled so the major bump is paid once:
- Module path go-micro.dev/v5 -> go-micro.dev/v6 across all imports + go.mod.
- TLS verification on by default (was off). MICRO_TLS_SECURE removed;
MICRO_TLS_INSECURE=true opts out for self-signed/dev.
- micro.NewService(name, opts...) is the canonical service constructor,
symmetric with NewAgent/NewFlow; micro.New kept as a deprecated alias;
the old name-less NewService(opts...) removed. Generators emit NewService.
Also ports the JWT auth token provider in-module (go-micro.dev/v6/auth/jwt/token
on golang-jwt/jwt/v5), dropping the v5-pinned github.com/micro/plugins/v5/auth/jwt
and the deprecated dgrijalva/jwt-go.
Docs/README/landing updated to v6 and @latest; v5->v6 migration guide added;
CHANGELOG cut as [6.0.0]. Blog posts left at their historical versions.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Agent Tool Wrappers
Middleware around an agent's tool execution, the same way
client.CallWrapper and server.HandlerWrapper wrap RPCs.
Every tool call an agent makes runs through ai.ToolHandler:
type ToolHandler func(ctx context.Context, call ai.ToolCall) ai.ToolResult
type ToolWrapper func(ai.ToolHandler) ai.ToolHandler
WrapTool (exposed as micro.AgentWrapTool) registers a wrapper: it
takes the next handler and returns a new one. Code before next(...)
runs before the tool, code after runs after. That single seam covers
the whole lifecycle — before/after hooks, timing, metrics, retries,
inspecting results.
What this example does
One flaky weather service and one agent with two wrappers:
- observe — times every call and records a per-tool count, logging
the correlation ID (
call.ID) carried through from the provider. It observes; it changes nothing. - retry — re-runs a call whose result is an error, up to three attempts. The weather service fails the first time it's hit and succeeds after, so retry turns a transient failure into a success the model never sees.
Wrappers compose outermost-first: observe is registered first, so
it wraps retry and sees one logical call even when retry runs the tool
twice.
micro.NewAgent("forecaster",
micro.AgentServices("weather"),
micro.AgentProvider(provider),
micro.AgentAPIKey(apiKey),
micro.AgentWrapTool(m.observe, retry(3)),
)
Wrappers vs. guardrails
Developer wrappers run outside the built-in guardrails (MaxSteps,
LoopLimit, ApproveTool), so they see every call and its result —
including a guardrail's refusal. The flip side: a retry wrapper's
next is the full guardrail stack, so each retry is also counted by
loop detection. Keep LoopLimit at or above your retry count, or set
AgentLoopLimit(0) when a wrapper owns the repetition.
See the Agent Guardrails guide for the full picture.
Run
Needs an LLM provider key:
export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY, GEMINI_API_KEY, ...
go run main.go