12 · Agent as a Function Tool
How wrapping one agent as a tool.Tool lets an orchestrator agent delegate to a specialist — composition all the way down, with no routing code.
What this lesson demonstrates
You already know function tools: a typed Go function the model may call mid-run. This lesson swaps the function for a whole agent. agenttool.New adapts an *agent.Agent into an ordinary tool.Tool, so a top-level orchestrator agent can delegate to a specialist agent exactly as it would call any other tool — no hand-written routing.
Here the orchestrator (an “Assistant” instructed to answer in French) owns a WeatherAgent as a tool, and that weather agent in turn owns a leaf weather function. Ask about Amsterdam’s weather and the call cascades two levels deep, then returns in French.
The core: an agent becomes a tool
foundryprovider.AgentConfig{
Instructions: "You are a helpful assistant who responds in French.",
Config: agent.Config{
Name: "Assistant",
// agenttool.New adapts an *agent.Agent to a tool.Tool: its Call runs the
// inner agent with the model's {"query": ...} argument and returns the text.
Tools: []tool.Tool{agenttool.New(weatherAgent, agenttool.Config{})},
},
}
When the outer model decides it needs weather, it calls the WeatherAgent tool; the wrapper runs the inner agent with {"query": ...}, which may itself call the leaf weather function, and the answer bubbles back up.
What to notice
- The inner agent’s name and description become the tool’s contract.
agenttool.NewreusesWeatherAgent’sName()andDescription()— that’s the schema the outer model sees when deciding to delegate, so give the specialist a clear identity. - Two levels of tool-calling, zero routing logic. The orchestrator calls the
WeatherAgenttool; the weather agent calls itsweatherfunction. You wrote no dispatch code. - Different input shape. A plain function tool wraps a single argument as
Arg0; the agent-as-tool takes a{"query": "..."}object instead — itsCallfeedsqueryto the inner agent. The offline test asserts each shape. - Construction is factored out.
newWeatherAgentandnewAssistantexist so the test builds both agents offline with a fake credential and asserts that wrapping the weather agent yields a tool namedWeatherAgentexposing aqueryproperty.
How it maps to the SDK
functool.MustNew builds the leaf weather tool by inferring its JSON schema from a plain typed Go function; agenttool.New builds the higher-order tool from an agent. Both produce a tool.Tool, so the orchestrator treats specialist agents and plain functions uniformly. This is how you assemble specialists into a hierarchy of Foundry-backed agents without a bespoke orchestration layer.
Run it
go run ./tutorial/02-agents/agents/step12_as_function_tool
The offline structural test runs anywhere; the live end-to-end run needs az login + FOUNDRY_PROJECT_ENDPOINT and is gated behind AF_LIVE=1.
Key takeaways
agenttool.Newturns a whole agent into atool.Tool, so an orchestrator can delegate to a specialist exactly as it would call any function — no hand-written routing.- The inner agent’s name and description become the tool’s contract — that’s the schema the outer model reads when deciding to delegate, so give the specialist a clear identity.
- The input shape differs from a plain function tool. A function tool wraps a single argument as
Arg0; the agent-as-tool takes a{"query": "..."}object, feedingqueryto the inner agent. - Two levels of tool-calling with zero dispatch code: the orchestrator calls the
WeatherAgenttool, which calls its leafweatherfunction, and the answer bubbles back up (here, returned in French).
Further reading
- step10 · Agent as an MCP Tool — expose the same agent-as-tool adapter over MCP for cross-process reuse.
- 02 · step03 — Using Function Tools — the leaf function-tool mechanism this composes on top of.
- providers · A2A (Agent2Agent) — delegate to a remote specialist instead of an in-process one.
Next: 17 · Additional AI Context