项目文件夹

文件
Asim Aslam 4311b73361 Enhance ADK vs Go Micro comparison and apply lint fixes (#2994)
* docs: compare Go Micro with Google ADK in the comparison guide

Adds a 'vs Agent Frameworks (Google ADK)' section: ADK builds an agent,
Go Micro builds the distributed system the agent lives in (agents are
services in the mesh). Covers the category difference, a feature table,
when to choose each, and MCP/A2A interoperability.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

* docs: replace ADK comparison slogan with concrete explanation

State plainly what each tool provides (ADK builds an agent process; Go Micro
builds the surrounding service mesh) instead of marketing phrasing.

* lint: apply golangci-lint autofixes; exclude ST1003 and demo errcheck

Mechanical, behaviour-preserving fixes applied by 'golangci-lint run --fix':
gofmt, misspell (US spelling), usestdlibvars (http.Method*/Status*), unconvert,
and the auto-fixable staticcheck simplifications (QF*, S1017/S1019/S1023/S1039).

Config: exclude ST1003 (remaining offenders are exported API renames, e.g.
web.Id, which would break compatibility) and skip errcheck for examples/ and
internal/harness/ (demo code where fire-and-forget is intentional).

Build and test compilation verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

* lint: WIP cleanup checkpoint (errcheck config + partial fixes)

Checkpoint of an in-progress golangci-lint cleanup (background pass). Builds
cleanly; lint is not yet zero. Follow-up commit will complete the cleanup and
switch CI to a blocking full-tree lint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 17:21:47 +01:00
..

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