DEV Community

Philip Stayetski
Philip Stayetski

Posted on

Run an AI Agent That Calls Other Agents as Tools — What “Call” Actually Means on the Wire

You want to run an AI agent that calls other agents as tools. An orchestrator that hands subtasks to a research agent, a coding agent, a human-approval agent. On paper, this is just tool calling — the same mechanism as a calculator or a web-search tool. In practice, "calling an agent" is two problems stacked together, and most tutorials only solve one of them.

The first problem is framework-level tool calling: the interface the model uses to discover and invoke a tool. The second is transport-level agent reachability: whether one agent's process can actually open a connection to another agent's process. They are different layers, and confusing them is why multi-agent systems that demo beautifully on a laptop fall apart the moment the agents live on different machines.

Tool calling is an interface, not a connection

Start with what the framework layer actually does. Function calling in an LLM API gives the model a set of typed functions with JSON schemas; the model returns a structured call, and your runtime executes it. MCP standardizes that further — tools become resources a client can discover and invoke, with the server running over stdio or HTTP.

Both are genuinely useful. MCP in particular is a real step forward: one client talks to many servers, and the ecosystem is growing fast. But notice what both of them assume: that the tool's process is reachable. A stdio MCP server lives in your process tree. An HTTP MCP server lives behind a URL that has to resolve, route, and accept your connection. Neither layer has any mechanism for making an agent on a laptop behind NAT reachable from an agent in a cloud VPC. That is not their job.

The part everyone skips: the other agent has to be reachable

Here's the scenario that breaks the demo. Your orchestrator runs on a VM in the cloud. The agent you want to call as a tool — the one holding the private data, or the one that can trigger an action only it can perform — runs on a laptop at home, or inside a customer's private network. The framework layer is ready: the orchestrator knows the tool exists, knows its schema, and can emit a valid call. Then the call goes out and dies. No route. NAT. A firewall that only allows outbound. An IP that changed this morning.

This is the transport problem, and it's the half of "calling an agent" that tool-calling frameworks explicitly don't solve. The usual workarounds each cost you something: expose a public endpoint (inbound port, static IP, DNS to babysit), poll a shared queue (latency and state), or run everything on one host (fine for a demo, wrong for production).

What transport-level agent reachability actually means

For agent A to call agent B as a tool, A's process needs a stable, working path to B's process. That's a networking problem, and it has a networking answer: an overlay network built for agents. Same family as a mesh VPN, with the agent use case in mind:

  • A permanent virtual address per agent, surviving IP changes and moves between clouds.
  • Encrypted UDP tunnels — X25519 key exchange, AES-GCM — so agent traffic is not plaintext on the public internet.
  • NAT traversal via STUN, hole punching, and relay fallback, so agents behind NAT are reachable without opening inbound ports.
  • Explicit trust: per-peer handshake, mutually approved, so "connected" never silently means "trusted."

The point of this layer: reachability stops being an assumption. When an agent is on the network, it has an address other agents can reach, wherever it runs.

Run an AI agent that calls other agents as tools: the two-layer stack

So the working shape of a multi-agent system has two layers, and you want both.

Layer one — the framework: the model discovers tools and emits structured calls. Function calling, or MCP with a client and servers.

Layer two — the transport: the processes can reach each other. Stable addresses, encrypted tunnels, a trust relationship.

Here's what that looks like in practice. Keep MCP as your framework layer — it's good at that. Put an agent-native network underneath it. Pilot Protocol, for example, ships an MCP server (pilot-mcp) that bridges the two: your MCP client discovers other agents as tools, and each tool call travels over an encrypted tunnel to a peer behind NAT. The model sees an ordinary tool; the wire sees a reachable peer.

The transport layer also gives you the plumbing that makes calls land:

# establish mutual trust with the agent you want to call
pilotctl handshake <peer> "orchestrator calling you as a tool"
pilotctl trust          # confirm mutual trust

# then call it — stable address, encrypted tunnel
pilotctl send-message <peer> --data '{"task": "summarize the incident", "return": "tool_result"}'
Enter fullscreen mode Exit fullscreen mode

Because the tool layer and transport layer are separate, the tools themselves can be delivered the same way. Pilot's app store ships capability apps as typed IPC services — JSON in, JSON out, auto-spawned on install, discoverable by the 243k+ agents on the network. The loop is pilotctl appstore catalogueinstallcall:

pilotctl appstore catalogue
pilotctl appstore install <id>
pilotctl appstore call <id> <method> '{"query": "..."}'
Enter fullscreen mode Exit fullscreen mode

The model's tool call becomes a JSON message to a local, signature-verified app. Framework on top, transport underneath — both explicit instead of assumed.

Why you need both

Skip the framework layer and you have reachable agents nothing can invoke: the processes can talk, but no model is driving them in a loop. Skip the transport layer and you have a beautiful tool-calling setup where every call to another agent dies with a connection error at deploy time. The first is a design gap. The second is the one that costs you a weekend.

The honest takeaway: MCP and function calling solved a real problem — the interface. Don't bolt a custom tool-calling protocol onto an overlay; use the standard framework layer. And don't treat reachability as an implementation detail of tool calling; it's a network property. Solve the interface with the frameworks the ecosystem standardized, and solve reachability with an agent-native network underneath — permanent addresses, NAT traversal, and explicit trust.

Run an AI agent that calls other agents as tools, and it will fail on the wire before it fails on the schema. Build both layers, and "calling an agent" becomes what it always looked like in the demo: one line, and it just works.


Get started:

curl -fsSL https://pilotprotocol.network/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Then read the Pilot Protocol docs for the MCP bridge and app store commands. Source: github.com/pilot-protocol.

Top comments (0)