Tool Composition for Google ADK Agents
The ADK tool limitations doc calls out a constraint that surprises every team eventually: a single Google ADK agent can use at most one built-in tool. The naive workaround — "let me add three tools to my agent" — silently fails.
This page explains the constraint, the official workarounds, and how to verify your tool topology is right using TraptureIQ.
The constraint
In Gemini's tool-calling model, you can attach one of:
- One built-in tool (e.g.,
google_search,vertex_ai_search,code_execution), or - Multiple custom function-call tools
You cannot mix two built-in tools on the same agent. Attempting to do so either throws at runtime or — worse — silently ignores one of them.
The three official workarounds
1. AgentTool.create() — nest agents as tools
Wrap a child agent (with its own single built-in tool) as a tool on the parent agent. The parent delegates to the child when relevant.
search_agent = Agent(name="search", tools=[google_search])
parent = Agent(
name="research_assistant",
tools=[
AgentTool.create(agent=search_agent),
# ... other custom function tools
],
)
The parent uses many tools (one of which happens to be an agent that itself uses a built-in tool). This is the most common workaround.
2. bypass_multi_tools_limit=True for Google Search + VertexAI Search
A specific exception exists for these two together — set the flag and you can attach both. See the ADK limitations doc for caveats.
3. Sub-agent delegation
If your top-level agent doesn't itself need a built-in tool, configure it as a router that delegates to specialized sub-agents — one for search, one for code execution, etc. The router uses no built-in tool; each sub-agent uses one. See ADK on agent composition and A2A for remote delegation.
Checklist
1. Inventory each agent's tools
For every registered Google ADK agent, list the tools it uses. If any agent has more than one built-in tool, refactor before production.
2. Use AgentTool.create() as the default composition pattern
Default to nested agents over flag flips. They're more debuggable: each child appears as its own span in Traces, so you can see exactly which sub-agent fired.
3. Prefer local sub-agents over A2A unless you have a reason
ADK supports both local sub-agents (in-process composition) and A2A (remote agent-to-agent calls). Local sub-agents are faster and easier to debug. Use A2A when:
- The sub-agent is owned by a different team
- The sub-agent has independent scaling needs
- The sub-agent is written in a different language
- You need a formal API contract between the two
4. Verify tool calls in Traces
After deploying, open a Trace for a session that exercises your tool topology. You should see:
- One span per tool invocation
- Spans for sub-agent delegations (with their own child spans)
- Inputs and outputs for each tool call
If a tool you expected to fire is missing from the trace, the limit was probably violated and silently dropped the tool.
5. Keep tool surfaces small per agent
A practical limit is 5-7 custom tools per agent. Beyond that, Gemini's tool-selection accuracy drops measurably. Split into sub-agents instead.
Anti-patterns
- Adding two built-in tools "to see what happens" — One gets silently ignored. Verify in Traces.
- One mega-agent with 15 tools — Tool-selection accuracy degrades. Split by domain.
- A2A for every sub-agent call — Adds latency, network failure modes, and observability complexity. Use local sub-agents unless you need the boundary.
- Custom tools that wrap external APIs without auth — Use ADK's authorization patterns — agent-auth or user-auth — not bare API calls.
Where to investigate
- Tool-call spans per session → Traces
- Tool error rates over time → Logs (filter by
tool.error) - Per-agent tool topology audit → Viewing Your Agents
References
- ADK: Tool limitations
- ADK: A2A overview
- ADK: Safety / authorization