Skip to content

Protocols for tools and for other agents

The first lesson of this course ended on a cost. When every agent calls every tool in its own way, each pair of agent and tool needs its own adapter. From one tool to many systems called this the N x M integration problem. In this lesson we look at the two kinds of shared protocol that answer it. The Model Context Protocol (MCP) connects an agent to tools and data. Agent-to-agent protocols, such as the Agent2Agent protocol (A2A), connect an agent to another agent, often one that another organization runs. Then we go back to the support agent of Guardrails in layers and ask what its defense layers do for a connection that a protocol makes easy to add.

Take a shop with three agents: the support agent, an agent that writes product pages and an agent that plans stock. Between them they use eight systems, the order database and the ticket system among them. If each agent calls each system in its own way, the shop writes and maintains 3 x 8 = 24 adapters. When the ticket system changes its interface, three of those adapters change with it.

With a shared protocol, each agent speaks the protocol once and each system is wrapped once. The shop builds 3 + 8 = 11 pieces. A new agent is one more piece and can use all eight systems. A new system is one more piece, and all three agents can reach it [1].

The things an agent connects to come in two kinds, with a protocol for each [1]. A tool takes a call with arguments and returns a result in one step, such as “look up order 4471”. Another agent takes a goal, such as “find out why this parcel is late”, and decides for itself how to reach it. It may work on the goal for minutes or days before it reports back. MCP is the standard for the first kind, and agent-to-agent protocols are the standard for the second [2].

The Model Context Protocol for tools and data

Section titled “The Model Context Protocol for tools and data”

MCP has three roles [3]. The host is the application a person uses, such as a coding agent or a chat app. Inside the host, a client holds the connection to one server. A server wraps a system and offers what that system can do. They exchange JSON-RPC 2.0 messages, a standard format for a remote procedure call (RPC) and its response. A server can offer tools, which the model calls, resources, which are data for the model or the person to use, and prompts, which are message templates a person picks. A client can in turn offer the server elicitation, which lets the server ask the person for more information [3]. Revision 2026-07-28 of the specification marks two older client features as deprecated. Roots let a client tell a server which folders to use, and sampling lets a server ask the client’s model for a completion. New servers and clients should not start to use either of them [4].

On the model’s side, the loop you built in this course stays the same. The model asks for a tool with a tool_use block, and the loop sends back a tool_result. The tool now runs somewhere else. The client sends the call to the server with a tools/call request, and the server’s answer becomes the result [3]. The tools of the support agent could come from a few servers, such as one for the ticket system and one for the shop’s orders. The other two agents in the shop could connect to the same servers.

Connecting an agent to your systems with MCP and Connecting your first tool server are the hands-on side of this section. One point from the specification matters for the rest of this lesson. The protocol has no way to make a host follow its security rules. It asks the host to get the person’s consent before a tool runs and to treat a tool’s description as untrusted unless the server is trusted, and the host decides how to do it [3].

Agent-to-agent protocols for work across organizations

Section titled “Agent-to-agent protocols for work across organizations”

A2A is an open protocol for agents that different teams built, with different frameworks, and that don’t show each other how they work inside [5]. The agent that asks is the client, and the agent that carries out the task is the remote agent. A delegation over A2A goes through discovery, a task and its results.

Discovery. A remote agent publishes an Agent Card, a JSON document with its name, its skills, the address to call and the authentication it requires. A client finds the card at a fixed path on the agent’s domain, /.well-known/agent-card.json, in a registry of agents, or in its own configuration [5].

The task. The client sends a message made of parts, and a part is text, a file or structured data. The remote agent works on it as a task, which has an id and a state, such as working, waiting for input, completed or failed. A task can run for a long time. The client asks for the task’s state, follows it over a stream, or has the remote agent post updates to an address the client gave it [5].

The results. What the task produces comes back as artifacts, such as a document or structured data, each made of parts [5].

The remote agent keeps its plan, its memory and its tools to itself [5]. You see its card and what it sends back. That is what makes it an agent you delegate to rather than a tool you call, and it is also why a delegation costs more than a tool call. What every extra agent costs counted the tokens and steps that a handoff between agents adds inside one program. A handoff to another organization’s agent adds its prices and its outages to that bill.

Here is an Agent Card for a courier’s agent. The courier, its addresses and its skills are invented for this lesson. The field names follow a2a.proto, the file that version 1.0 of the A2A specification names as its normative definition [5].

{
"name": "Parcel desk",
"description": "Answers questions about parcels that Example Parcels delivers.",
"supportedInterfaces": [
{"url": "https://agents.parcels.example/a2a", "protocolBinding": "JSONRPC", "protocolVersion": "1.0"}
],
"provider": {"organization": "Example Parcels", "url": "https://parcels.example"},
"version": "2.3.0",
"capabilities": {"streaming": false, "pushNotifications": true},
"securitySchemes": {
"partnerKey": {"apiKeySecurityScheme": {"location": "header", "name": "X-Partner-Key"}}
},
"securityRequirements": [{"schemes": {"partnerKey": {"list": []}}}],
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "track-parcel",
"name": "Track a parcel",
"description": "Give an order number and a postal code. Returns where the parcel is and when it arrives.",
"tags": ["tracking"]
},
{
"id": "answer-delivery-ticket",
"name": "Answer a delivery ticket",
"description": "Give the full text of a customer's ticket. Returns a reply you can post to the customer.",
"tags": ["support"]
}
]
}

The card says what the agent offers and how to call it. The skills describe the courier’s services, and a request doesn’t name one [5]. The client sends a message, and the courier’s agent decides how to answer it. The card says nothing about what the courier’s agent does with a ticket once it has one.

Checkpoint · sort

A shared protocol makes a connection cheap to add. The support agent could reach the courier’s agent with the address of one card and a key. That is the purpose of the protocol, and it is also the risk. Each connection brings text into the model’s context that you didn’t write, and each one is a way for data to leave [1]. The model reads the tool descriptions of an MCP server and the artifacts a remote agent returns as it read the recipe page, and a planted instruction in them works in the same way. The message you send to a remote agent is an outbound call, like post_reply. Once it is sent, what you put in it is out of your control.

What the other side may do with your data is for you and the other side to decide, and the protocols leave it open. MCP leaves consent and access control to the host [3]. A2A requires the remote agent to authenticate every request, and it leaves the rules for what an authenticated caller may do to each agent’s own authorization model [5]. An encrypted, authenticated connection tells you who is at the other end. It doesn’t tell you what they do with a ticket.

So the defense layers of the support agent apply to a protocol connection as they apply to any other tool. Picture the courier’s agent behind one more tool, ask_courier(order_id, postal_code), in the loop of Guardrails in layers. The model chooses the two arguments, and the tool’s own code writes the message: a fixed tracking question as text, with the order number and postal code as a structured data part. The model can’t add anything else to it.

  • The permission check looks at the arguments before the message is written. A rule in the loop can allow an order that belongs to the ticket’s author and a postal code, and refuse everything else. Because the courier’s agent picks how to answer, the control is on what you send.
  • The output filter reads the message before it leaves, as it reads a reply.
  • The approval gate can hold a delegation until a person has seen what it sends.
  • The artifact that comes back is untrusted input, like a fetched page. A planted line in it can steer the model, so every call the model makes after reading it still meets the permission check and the gate.
  • Monitoring sees your side only. Your trace ends at the call, because the remote agent keeps its steps to itself. What you log about the messages you sent and the artifacts that came back is all the evidence you have.

The system prompt still lowers the odds, and it is still the weakest layer. A line that says “never send a ticket to a partner” depends on the model following it, as it did for the recipe page.

Checkpoint · scenario

A partner offers its agent over an agent-to-agent protocol. It can answer delivery questions, and the partner proposes that your support agent sends it every delivery ticket in full. What do you decide before you enable it?

Exercise

Judge the connection the courier proposes, on paper. The courier offers the Agent Card in this lesson, points at its answer-delivery-ticket skill, and proposes that the support agent sends every delivery ticket in full and posts the reply that comes back to the customer. Deciding before you connect is cheaper than finding out from a log.

Write a note of about ten lines in three parts. First, list what the connection can read and what it can send, in both directions. Second, take the layers in the fixture of Guardrails in layers, site/examples/building-agents/guardrails-in-layers/: the system prompt, the permission check, the output filter, the approval gate and the monitor in the alerts step. For each one, say whether it applies to this connection and where in the flow it acts. Third, write the one trust decision you would make before you enable the connection.

A good note says that the courier would read everything in a ticket: the customer’s name and address, the order, any link and any planted paragraph. It says that the courier sends back text that the model reads, and that the proposal posts that text to the customer with no check of yours in between, and that updates can arrive later at the address you give for notifications. It notes that a request names no skill, so the skill on the card doesn’t limit what the courier’s agent does with a full ticket. It puts the permission check on what the loop sends, the filter and the gate on the message and on the reply, and it says the monitor sees only your side. A good trust decision is concrete, such as “send only a fixed tracking question with the order number and postal code, and write the reply ourselves”. What would the courier have to show you before you sent it full tickets?

Stretch: Write ask_courier as a Python function in the style of permitted() in agent.py of the fixture. It takes an order number and a postal code, refuses an order that isn't the ticket author's, and builds the message from a fixed tracking question and those two fields.

Recap

  1. A shared protocol turns N x M adapters into N plus M: each agent speaks the protocol once and each system is wrapped once [1].
  2. The Model Context Protocol connects an agent to the tools, resources and prompts that servers offer, and the loop still sends each tool call and returns its result [3].
  3. Agent-to-agent protocols such as A2A cover discovery through an Agent Card, delegation as a task, and results as artifacts, between agents that keep their internals to themselves [5].
  4. Neither protocol decides what the other side may do with your data, so each connection is a trust decision you make before you enable it.
  5. Treat a remote agent as a tool that reads and sends. Its message goes through the permission check, the filter and the gate, and what comes back is untrusted input.

You can now

  • Mitigates injection, exfiltration and over-permission in a running agent

  1. Addy Osmani, Ivar Soares Urdalen, Leo Simons. Agent protocols, MCP and A2A. Agent Engineer Course. Course. AEC-14
  2. The A2A project contributors. A2A and MCP: Detailed Comparison. a2a-protocol.org. Reference. A2A and MCP
  3. Anthropic and the MCP contributors. Model Context Protocol specification 2026-07-28. modelcontextprotocol.io. Reference. MCP specification
  4. Anthropic and the MCP contributors. Deprecated Features, Model Context Protocol specification 2026-07-28. modelcontextprotocol.io. Reference. MCP deprecated features
  5. The A2A project contributors. Agent2Agent (A2A) Protocol Specification, version 1.0.0. a2a-protocol.org. Reference. A2A specification