Appearance
Agent-to-Agent Communication
Every tool you connect to an agent the naive way, writing a custom Python wrapper around one specific API, is a wrapper you'll maintain forever, and one that only works inside the one framework you wrote it for. Switch from LangChain to a hand-rolled loop, or from Claude to Gemini, and every tool integration you built has to be rewritten. This gets expensive fast once an agent needs to reach a database, a filesystem, three SaaS APIs, and another agent someone else on your team built. This page covers the standard that fixes that, and the simpler pattern underneath it for when an agent just needs to hand work to another agent.

What you'll learn
- Why hard-coded tool wrappers don't survive a framework or model change
- The Model Context Protocol (MCP): a real, model-agnostic standard for connecting agents to tools
- The simplest possible pattern for one agent to call another directly
The problem: every framework wants its own tool format
Function calling itself isn't the hard part, every major model API supports it, and the schema looks roughly the same everywhere. What's expensive is everything around it: authentication, credential handling, permission boundaries, and the fact that a tool wrapper written for one agent framework usually can't be dropped into another without rewriting it. A team that builds a "check the internal database" tool for their LangChain agent has to build it again, from scratch, the day someone wants the same capability from a Claude Code session or a custom loop like the one from Day 1.
The Model Context Protocol (MCP) , an open standard from Anthropic, exists specifically to break that coupling. It separates the tool from the agent framework calling it, the same way a REST API separates a service from whichever client happens to call it.
How it's structured
MCP splits the world into two roles. An MCP server wraps a real capability, a database, a filesystem, a SaaS API, and exposes it through a standard interface. An MCP client, embedded in your agent, talks to any MCP server using the same protocol regardless of what that server wraps. Write the server once, and any MCP-compatible agent (Claude Code, and a growing list of others) can use it without custom integration code.
Two things make this worth the extra layer instead of just writing a direct API wrapper: the client never sees the server's credentials (your database password lives on the server side, not inside the agent's context), and the server can enforce its own boundaries, reject any file read outside a specific directory, for instance, independent of what the agent asks for. The security boundary lives with the tool, not with whichever agent happens to be calling it that day.
Under the hood it's JSON-RPC over stdio (for a local server on your own machine) or SSE (for a remote one). You don't usually write this by hand, you configure a server and a client library handles the wire format, but it's worth seeing once, because it demystifies what "MCP-compatible" actually means:
json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "query_customer_database",
"arguments": { "customer_id": 4821 }
},
"id": 1
}The server executes the real query, keeping the connection string and credentials entirely on its own side, and replies with plain structured content the agent can read.
The simpler case: one agent calling another directly
MCP solves the tool interoperability problem. Sometimes what you actually need is smaller: one agent handing a subtask to another agent, in-process, with no protocol involved at all. If your research agent needs a second opinion from a specialized coding agent, you don't need MCP for that, you just call it like any other tool:
python
def delegate_to_coding_agent(task: str) -> str:
"""Tool the research agent can call to hand off implementation work."""
return run_agent(task, max_steps=15) # the same loop from Day 1, a second time
RESEARCH_AGENT_TOOLS = [
read_file_tool,
web_search_tool,
{
"name": "delegate_to_coding_agent",
"description": "Hand an implementation task to a specialized coding agent",
"input_schema": {
"type": "object",
"properties": {"task": {"type": "string"}},
"required": ["task"],
},
},
]From the calling agent's point of view, another agent is just a tool that happens to be smart. This is the seed of the pattern Day 3's multi-agent workflows builds on properly, with shared state, checkpoints, and a human-approval gate before anything consequential happens. Reach for MCP when you're standardizing access to a tool that multiple agents or frameworks need to share; reach for direct delegation when it's just your own agents handing work to each other inside one system.
What goes wrong
| Mistake | How you notice it | The fix |
|---|---|---|
| Writing a custom wrapper for every tool, every framework | The same integration gets rebuilt from scratch every time you switch tools or frameworks | Use MCP for anything more than one agent or framework needs to reach |
| Letting the agent hold credentials directly | An API key or DB password shows up in the agent's context or logs | Keep credentials on the MCP server side, the client should never see them |
| No boundary on what a delegated agent can do | A "helper" agent takes an action outside the scope it was delegated | Give a delegated agent its own restricted tool list, not the full set the parent agent has |
| Infinite delegation loops | Agent A delegates to Agent B, which delegates back to Agent A | Cap delegation depth, same as you'd cap max_steps on a single agent loop |
Confirm it worked
For an MCP server, the fastest check is whether a client can discover its tools without any hand-written glue code:
bash
# Using Claude Code's MCP inspector, or any MCP-compatible client
mcp-client list-tools --server ./my-database-server
# should list every tool the server exposes, with schemas, no custom code requiredFor direct agent delegation, confirm the handoff actually happens and comes back with real output, not a stub:
python
result = delegate_to_coding_agent("Write a function that validates an email address")
assert "def " in result # the delegated agent actually produced code, not a placeholderNext: Day 3 , Agent Skills, where multi-agent coordination and memory come together properly.