Everything is a tool¶
If something exposes a useful capability, it should be usable as a tool — regardless of whether it is a function, an agent, a plan, an MCP server, or a whole pipeline.
This is the composition rule that holds the framework together. Most agent frameworks distinguish sharply between functions, agents, chains, workflows, plugins, integrations, and tools. LazyBridge collapses these into a single concept.
What can be a tool¶
| Source | How | Where it lives |
|---|---|---|
| A Python function | Pass it directly to Agent(tools=[...]) |
Your code |
| Any callable | Wrap with Tool(...) or Tool.wrap(callable, name=...) |
Your code |
Another Agent |
Pass it directly: Agent(tools=[other_agent]). Its name= becomes the tool name. |
Hierarchical / supervisor patterns |
| The same agent under a different name | other_agent.as_tool("alias") |
When you want a different surface name than other_agent.name |
A Plan |
Agent(engine=Plan(...), name="...") then pass that agent in tools=[...] |
Reusable deterministic pipelines |
| A provider-native capability | Agent(engine=LLMEngine("claude-haiku-4-5"), native_tools=["web_search"]); the NativeTool enum (NativeTool.CODE_EXECUTION, …) when you want IDE autocompletion |
Provider-side, no code |
| An MCP server | MCP.stdio(...) or MCP.http(...) passed in tools=[...] |
External tool ecosystems |
| A pre-built JSON schema | Tool.from_schema(name, description, parameters, func) |
OpenAPI bridges, third-party registries |
In every case, the agent that consumes the tool sees the same Tool
object. There is no special-case glue for "agent calls function" versus
"agent calls another agent" versus "agent calls MCP server".
Composition is recursive¶
Because every capability is a tool, you can compose at every level.
plain function
│
▼ Tool(...)
tool ──────────► added to an Agent
│
▼ agent.as_tool("search", ...)
tool ──────────► added to a higher-level Agent
│
▼ Agent(engine=Plan(...)).as_tool(...)
tool ──────────► added to a top-level orchestrator
A short illustration:
from lazybridge import Agent, LLMEngine
researcher = Agent(
engine=LLMEngine("claude-haiku-4-5"),
name="research",
tools=[web_search, fetch_url],
)
writer = Agent(
engine=LLMEngine("claude-haiku-4-5"),
tools=[researcher],
)
The writer agent now has a tool called research (taken from the
researcher's name=) whose implementation is a fully-fledged sub-agent
with its own model, prompt, tools, and cost tracking. The supervisor
pattern, hierarchical planning, and "agents as tools" are all the same
primitive — one Agent, in another Agent's tools=[...].
Why this matters¶
One thing to learn. You don't need separate concepts for "function
calling", "tool use", "sub-agents", "delegation", "subgraphs", or "node
edges". You only need to learn how a Tool works.
One contract to test. Every tool — function, agent, MCP, plan — speaks
the same input/output contract. A MockAgent is a drop-in replacement for
a real one. Your test fixtures stay readable.
Free recursion. Cost, token counts, latency, and errors roll up
transitively through nested tool calls. A daily_news_report agent that
calls a region_pipeline that calls a writer_agent reports total cost
and total tokens at the top, regardless of how many levels are nested in
between.
No orchestration glue. A pipeline is just a Plan. A Plan is a tool.
A tool is something an agent already knows how to call. You don't write
glue — you compose.
The trade-off worth naming¶
"Everything is a tool" tempts you to over-decompose. Sub-agents are not free. Every nested agent adds latency, an LLM call (if its engine is an LLM), and prompt-construction overhead.
Use a sub-agent when:
- It has a distinct responsibility with a clear input and output.
- A smaller / cheaper / specialised model is appropriate.
- The output type is structured and the parent agent benefits from a validated payload rather than free-form text.
- You want to reuse the same capability from multiple parents.
Don't use a sub-agent merely because the diagram looks nicer with one. A single agent with three tools often beats three agents with one tool each.
See also¶
- Mental model — where Tools sit in the Engine + Tools + State decomposition.
- Progressive complexity — when "wrap the
agent as a tool" is the right next step versus when to reach for a
Plan. - Guides → Tool (coming in Phase 2) — the three schema modes
(
signature/llm/hybrid) and theTool.from_schemaescape hatch. - Guides → As tool (coming in Phase 2) — the full mechanics of
agent.as_tool(...)including the optional verifier loop. - Guides → MCP (coming in Phase 2) — connecting external tool ecosystems through stdio and HTTP transports.