⏳
Loading cheatsheet...
MCP, A2A, ACP, agent protocols, orchestration models, and production architecture patterns for modern agent systems.
| Protocol | Creator | Scope | Status |
|---|---|---|---|
| MCP (Model Context Protocol) | Anthropic | Agent → Tool / Data | GA (Nov 2024) |
| A2A (Agent-to-Agent Protocol) | Agent ↔ Agent | v0.3 (Jul 2025) | |
| ACP (Agentic Commerce Protocol) | OpenAI / Stripe | Agent Commerce | Draft (2025) |
| Feature | MCP | A2A | ACP |
|---|---|---|---|
| Creator | Anthropic | OpenAI + Stripe | |
| Purpose | Agent-to-Tool | Agent-to-Agent | Agent Commerce |
| Transport | stdio / SSE / Streamable HTTP | HTTP + SSE (streaming) | HTTP + OAuth |
| Discovery | Manual config / mcp.json | Agent Card (.well-known) | Merchant manifest |
| Auth | Bearer tokens, API keys | OAuth 2.1, API keys, mTLS | OAuth 2.1, multi-factor |
| Data model | Tools, Resources, Prompts | Tasks, Messages, Parts | Catalogs, Carts, Orders |
| Streaming | Yes (SSE) | Yes (SSE) | Planned |
| State management | Server-managed context | Task lifecycle (state machine) | Order state machine |
| Key use case | Give an agent a calculator, database, or API | Two agents collaborate on a project | Agent shops and purchases on behalf of user |
| Specification | github.com/modelcontextprotocol | github.com/google/A2A | openai / stripe guides |
| Concept | Description |
|---|---|
| Agent Card | JSON manifest at /.well-known/agent.json — describes capabilities, skills, auth |
| Task | Unit of work sent between agents — has a lifecycle (submitted → working → completed/failed) |
| Message | Communication within a task — contains Parts (text, file, data) |
| Part | Typed content: TextPart, FilePart, DataPart |
| Skill | Named capability an agent offers (e.g., "web-search", "code-review") |
| Streaming | Server-Sent Events for real-time task updates |
{
"name": "Research Agent",
"description": "Performs deep web research and summarization",
"url": "https://api.example.com/a2a",
"version": "1.0.0",
"provider": {
"organization": "Acme AI",
"url": "https://acme.ai"
},
"capabilities": {
"streaming": true,
"pushNotifications": false,
"stateTransitionHistory": true
},
"authentication": {
"schemes": [{ "type": "oauth2", "flow": "authorizationCode" }]
},
"skills": [
{
"id": "web-search",
"name": "Web Search",
"description": "Search the web for real-time information",
"tags": ["search", "research", "real-time"],
"examples": ["Find latest news about X", "Research market trends"]
},
{
"id": "summarize",
"name": "Summarize",
"description": "Summarize long documents or article collections",
"tags": ["summarization", "nlp"],
"examples": ["Summarize these 5 articles"]
}
],
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"]
}| State | Description | Transition |
|---|---|---|
| submitted | Task created and queued | → working (agent picks it up) |
| working | Agent is actively processing | → completed | failed | canceled |
| completed | Task finished successfully | → terminal (end state) |
| failed | Task errored out | → terminal (can retry with new task) |
| canceled | Task canceled by sender | → terminal (end state) |
| input-required | Agent needs more info from sender | → working (after response) |
| Endpoint | Method | Description |
|---|---|---|
| tasks/send | POST | Send a new task or message to an agent |
| tasks/get | GET | Retrieve current task state and history |
| tasks/cancel | POST | Request cancellation of a task |
| tasks/stream | SSE | Subscribe to real-time task updates |
| tasks/sendSubscribe | POST + SSE | Send task and immediately subscribe to stream |
| Type | Fields | Use Case |
|---|---|---|
| Task | id, sessionId, status, history[] | Top-level work unit between agents |
| Message | role, parts[], metadata | Communication within a task (user/agent roles) |
| TextPart | type: "text", text | Plain text content |
| FilePart | type: "file", name, mimeType, bytes | Binary file (images, PDFs, etc.) |
| DataPart | type: "data", data (JSON) | Structured data payload |
| Field | Value |
|---|---|
| jsonrpc | 2.0 |
| method | tasks/send |
| params.id | auto-generated UUID |
| params.sessionId | optional — groups related tasks |
| params.message.role | "user" (the requesting agent) |
| params.message.parts[0].type | "text" |
| params.message.parts[0].text | "Research quantum computing advances in 2025" |
tasks/sendSubscribe endpoint lets you send a task and get SSE updates in a single connection. This avoids polling overhead and gives real-time progress to users. For long-running tasks, implement input-required state to prompt for clarification.| Scheme | How It Works | Use Case |
|---|---|---|
| API Key | Static key in Authorization header | Simple internal agent-to-agent calls |
| OAuth 2.1 (Authorization Code) | Redirect-based flow with consent | Third-party agent accessing your agent |
| OAuth 2.1 (Client Credentials) | Machine-to-machine token exchange | Server-to-server agent communication |
| mTLS | Mutual TLS certificate validation | High-security environments (finance, healthcare) |
| Shared Secret | HMAC-signed requests | Legacy / simple deployments |
| Practice | Details |
|---|---|
| OAuth 2.1 default | Always prefer OAuth 2.1 for production — it supersedes OAuth 2.0 |
| Least privilege scopes | Issue tokens with minimum required permissions per skill |
| mTLS for sensitive data | Use mutual TLS when agents handle PII, financial, or health data |
| Rate limiting | Protect agents from abuse — enforce per-client rate limits |
| Input validation | Sanitize all incoming task messages — agents are attack surfaces |
| Audit logging | Log all inter-agent calls for compliance and debugging |
// Agent Card Authentication Declaration
"authentication": {
"schemes": [
{
"type": "oauth2",
"flow": "authorizationCode",
"authorizationUrl": "https://auth.example.com/authorize",
"tokenUrl": "https://auth.example.com/token",
"scopes": ["research:read", "research:write"]
},
{
"type": "mtls",
"caCertificates": ["-----BEGIN CERTIFICATE-----..."]
}
]
}| Library | Install | Purpose |
|---|---|---|
| a2a-sdk | pip install a2a-sdk | Official A2A client/server SDK |
| google-adk | pip install google-adk | Google Agent Development Kit (native A2A) |
| langchain-a2a | pip install langchain-a2a | LangChain A2A integration |
| fastapi-a2a | pip install fastapi-a2a | FastAPI A2A server scaffolding |
# ── Minimal A2A Server (FastAPI + a2a-sdk) ──
from fastapi import FastAPI
from a2a.server import A2AServer, task_handler
app = FastAPI()
@a2a_server.task_handler("web-search")
async def handle_search(task: Task) -> Task:
"""Handle incoming search tasks from other agents."""
query = task.message.parts[0].text
results = await search_engine.query(query)
# Update task status and return results
task.status.state = "completed"
task.message = Message(
role="agent",
parts=[TextPart(text=str(results))]
)
return task
# Agent Card served at /.well-known/agent.json
a2a_server = A2AServer(
agent_card=AgentCard(
name="Search Agent",
description="Performs web searches",
skills=[Skill(id="web-search", name="Web Search")]
)
)
app.mount("/a2a", a2a_server.app)# ── A2A Client — Sending a Task ──
from a2a.client import A2AClient
client = A2AClient("https://api.example.com/a2a")
# Discover the agent
card = await client.get_agent_card()
print(f"Agent: {card.name} — Skills: {[s.id for s in card.skills]}")
# Send a task
task = await client.send_task(
message=Message(
role="user",
parts=[TextPart(text="Research LLM architectures for 2025")]
)
)
# Stream the response
async for event in client.stream_task(task.id):
if event.status:
print(f"State: {event.status.state}")
if event.message:
print(f"Agent: {event.message.parts[0].text}")| Entity | Description |
|---|---|
| Product Catalog | Standardized product listing API — agents can query availability, pricing, specs |
| Cart | Shopping cart management — add, remove, update quantities, apply discounts |
| Checkout | Payment processing flow with multi-step user authorization |
| Order | Order tracking — status updates, delivery info, returns, refunds |
| Price Comparison | Cross-merchant price comparison via standardized product schema |
| Receipt | Structured purchase confirmation for record-keeping and expense reporting |
| Step | Action | Agent Autonomy | User Approval |
|---|---|---|---|
| 1 | Discover merchants & product catalogs | Full autonomy | Not required |
| 2 | Search/filter products by criteria | Full autonomy | Not required |
| 3 | Compare prices across merchants | Full autonomy | Not required |
| 4 | Add items to cart | Full autonomy | Not required |
| 5 | Apply coupons / promotions | Semi-autonomous | Recommended |
| 6 | Review cart & total | Present summary | Required |
| 7 | Select payment method | Semi-autonomous | Required |
| 8 | Confirm purchase (checkout) | No autonomy | Required (multi-factor) |
| 9 | Process payment | No autonomy | Required (OTP / biometric) |
| 10 | Receive order confirmation | Notify user | Informed |
| 11 | Track order / handle returns | Semi-autonomous | Informed |
// ACP Checkout Request (simplified)
{
"cart_id": "cart_abc123",
"items": [
{ "product_id": "prod_001", "quantity": 1, "price": 49.99 },
{ "product_id": "prod_002", "quantity": 2, "price": 19.99 }
],
"discounts": [{ "code": "SUMMER20", "type": "percent", "value": 20 }],
"payment": {
"method": "card_on_file",
"last_four": "4242",
"authorization": {
"type": "multi_factor",
"user_verified": true,
"verification_method": "biometric",
"timestamp": "2025-07-15T10:30:00Z"
}
},
"shipping": { "address_id": "addr_home", "method": "express" }
}| Layer | Protocol | Analogy | Example |
|---|---|---|---|
| Tool Access | MCP | USB / peripheral bus | Agent queries a database via MCP server |
| Agent Communication | A2A | Network / internet | Research Agent sends findings to Writer Agent via A2A |
| Commerce | ACP | Payment gateway | Shopping Agent purchases items via ACP |
| User Interaction | AG-UI | Display / UI layer | Agent presents progress to the user |
# ── MCP + A2A Combined Agent ──
from a2a.client import A2AClient
from mcp import MCPServer
class OrchestratorAgent:
def __init__(self):
# MCP tools for this agent's own use
self.mcp = MCPServer(tools=["web_search", "file_system"])
# A2A clients for communicating with other agents
self.researcher = A2AClient("https://research.api/a2a")
self.writer = A2AClient("https://writer.api/a2a")
async def handle_request(self, user_query: str):
# Step 1: Send research task via A2A
research_task = await self.researcher.send_task(
message=Message(role="user", parts=[
TextPart(text=f"Research: {user_query}")
])
)
# Step 2: Get research results
findings = await research_task.completed()
# Step 3: Send writing task via A2A
write_task = await self.writer.send_task(
message=Message(role="user", parts=[
TextPart(text=f"Write blog post based on: {findings}")
])
)
return await write_task.completed()| Framework | Creator | Approach | A2A Support | Best For |
|---|---|---|---|---|
| LangGraph | LangChain | Graph-based orchestration with state machines | Native (v0.3+) | Complex workflows, production pipelines |
| CrewAI | CrewAI Inc. | Role-based crew collaboration | Native (via plugin) | Team-based task delegation |
| Google ADK | Agent Development Kit — first-class A2A | Native (built-in) | Google Cloud / Gemini agents | |
| Microsoft AutoGen | Microsoft | Multi-agent conversation framework | Community adapter | Research, conversational agents |
| OpenAI Swarm | OpenAI | Lightweight agent handoff | Experimental | Quick prototypes, simple handoffs |
| Pydantic AI | Pydantic | Type-safe agent framework | Planned | Type-safe Python applications |
| Feature | Details |
|---|---|
| State Graph | Define workflows as directed graphs with conditional edges |
| Checkpointing | Persist state at every step — resume after failures |
| Human-in-the-loop | Interrupt graph execution for human approval |
| Subgraphs | Nest agent workflows within parent graphs |
| Streaming | Token-level streaming from any node in the graph |
| Persistence | Built-in state persistence (SQLite, Postgres, etc.) |
| Feature | Details |
|---|---|
| Agents | Defined with roles, goals, and backstories |
| Tasks | Specific assignments with expected output format |
| Crews | Group of agents that collaborate on tasks |
| Processes | Sequential, Hierarchical, or Consensus-based |
| Tools | Custom tools + MCP integration |
| Memory | Short-term and long-term memory for agents |
# ── A2A-Enabled LangGraph Agent ──
from langgraph.prebuilt import create_react_agent
from langgraph_a2a import A2ADeployment
# Define the agent with tools
research_agent = create_react_agent(
model="claude-sonnet-4-20250514",
tools=[web_search_tool, scraper_tool, summarizer_tool],
name="researcher",
prompt="You are a research specialist. Find accurate, "
"up-to-date information and provide citations."
)
# Deploy as A2A endpoint
deployment = A2ADeployment(
agent=research_agent,
agent_card={
"name": "Research Agent",
"description": "Deep web research and fact-checking",
"url": "https://api.example.com/a2a",
"version": "1.2.0",
"capabilities": {
"streaming": True,
"pushNotifications": False
},
"skills": [
{
"id": "web-search",
"name": "Web Search",
"description": "Search the web for real-time info"
},
{
"id": "fact-check",
"name": "Fact Check",
"description": "Verify claims against sources"
}
]
}
)
# Run the A2A server
if __name__ == "__main__":
deployment.run(host="0.0.0.0", port=8000)# ── Multi-Agent System with LangGraph + A2A ──
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph_a2a import A2ANode
workflow = StateGraph(MessagesState)
# Add A2A-connected agent nodes
workflow.add_node("researcher", A2ANode(
endpoint="https://research.api/a2a",
agent_card_required=True
))
workflow.add_node("writer", A2ANode(
endpoint="https://writer.api/a2a"
))
workflow.add_node("reviewer", A2ANode(
endpoint="https://review.api/a2a"
))
# Define the workflow
workflow.add_edge(START, "researcher")
workflow.add_edge("researcher", "writer")
workflow.add_edge("writer", "reviewer")
workflow.add_conditional_edges("reviewer",
lambda state: "writer" if state.needs_revision else END
)
app = workflow.compile(checkpointer=checkpointer)| Component | Description |
|---|---|
| Agent | Core class — name, model, instructions, tools |
| Tool | Python function decorated with @tool or MCP server |
| Runner | Executes the agent loop (think → act → observe) |
| Session | Persistent conversation context across turns |
| A2A Server | Built-in HTTP server exposing agent via A2A |
| Authenticator | Handles OAuth 2.1 for incoming A2A requests |
# ── Google ADK Agent with A2A ──
from google.adk import Agent
from google.adk.tools import mcp_tool
from google.adk.a2a import A2AServer
# Create agent with MCP tools and A2A enabled
agent = Agent(
name="DataAnalyst",
model="gemini-2.5-pro",
description="Analyzes datasets and creates visualizations",
instruction=(
"You are a data analysis specialist. "
"Query databases, analyze trends, "
"and generate charts/visualizations."
),
tools=[
mcp_tool("sqlite://data.db"), # MCP database tool
mcp_tool("python://repl"), # MCP Python REPL
],
)
# Deploy with A2A — one line!
server = A2AServer(
agent=agent,
port=8080,
auth="oauth2" # Enable OAuth 2.1
)
server.start()| Protocol | Focus | Creator | Description |
|---|---|---|---|
| AG-UI | Agent-User Interaction | Various | Standards for how agents present UI — streaming text, progressive rendering, tool-use indicators, thinking displays |
| ANP | Agent Network Protocol | Various | Decentralized agent networks — peer-to-peer agent discovery and communication without central registries |
| AP2 | Agent Push Protocol | Various | Push notifications between agents — event-driven architecture where agents proactively notify each other of changes |
| WebMCP | HTTP-based MCP | Community | MCP over standard HTTP (vs stdio) — uses agents.json for discovery, more web-friendly deployment |
| Standard | Purpose |
|---|---|
| Streaming Text | Token-by-token text display with cursor animation |
| Tool Call Display | Show which tools the agent is invoking in real time |
| Thinking Indicator | Visual feedback during agent reasoning phases |
| Progressive Loading | Stream partial results as they become available |
| Error Recovery UI | Graceful error display with retry/skip options |
| Feature | Details |
|---|---|
| Transport | Standard HTTP POST (no stdio or SSE requirement) |
| Discovery | agents.json file at website root (like .well-known) |
| Benefits | Serverless-friendly, CDN-cacheable, firewall-friendly |
| Compatibility | Drop-in replacement for stdio MCP in most clients |
| Pattern | Description | Example |
|---|---|---|
| Orchestrator-Worker | Central agent delegates tasks to specialized workers | Manager assigns research, writing, and review tasks |
| Pipeline / Sequential | Agents process in a fixed sequence, output → input | Researcher → Writer → Editor → Publisher |
| Hierarchical | Multi-level management — managers manage sub-managers | CEO Agent → Team Lead → Individual Contributors |
| Peer-to-Peer | Agents communicate directly without central orchestrator | Two agents negotiate and collaborate as equals |
| Blackboard | Shared state that agents read/write independently | Multiple agents contribute to a shared knowledge base |
| Event-Driven | Agents react to events published to a message bus | Agent A publishes "data_ready", Agent B processes it |
| Scenario | Recommended Pattern |
|---|---|
| Simple linear workflow | Pipeline / Sequential |
| Complex task with dynamic routing | Orchestrator-Worker (LangGraph) |
| Large team with roles | Hierarchical (CrewAI) |
| Real-time collaboration | Peer-to-Peer (A2A native) |
| Knowledge accumulation | Blackboard pattern |
| Microservices integration | Event-Driven (AP2 + message queue) |
| Human-in-the-loop required | Orchestrator with interrupt checkpoints |
| Threat | Description | Mitigation |
|---|---|---|
| Prompt Injection | Malicious input manipulates agent behavior | Input sanitization, output validation, sandboxed execution |
| Tool Hijacking | Attacker tricks agent into calling unintended tools | Least-privilege tool access, approval workflows |
| Data Exfiltration | Agent leaks sensitive data through responses | Output filtering, PII detection, DLP policies |
| Agent Impersonation | Fake agent pretends to be a legitimate service | mTLS, OAuth 2.1, verified Agent Cards |
| Task Poisoning | Attacker injects malicious data into task stream | Message signing, content integrity checks |
| Denial of Service | Overwhelming agent with requests | Rate limiting, per-client quotas, circuit breakers |
| Check | Priority |
|---|---|
| All A2A endpoints use OAuth 2.1 or mTLS | Critical |
| Agent Cards served over HTTPS only | Critical |
| Input messages validated and sanitized | Critical |
| Tool execution sandboxed (Docker, gVisor) | High |
| Rate limiting on all agent endpoints | High |
| Audit logging for all inter-agent calls | High |
| PII detection and redaction in agent responses | Medium |
| Circuit breaker for downstream agent failures | Medium |
| Regular security review of Agent Card schemas | Medium |
| Penetration testing of agent endpoints | Recommended |
| Principle | Description |
|---|---|
| Single Responsibility | Each agent does ONE thing well — research, write, code, review |
| Clear Interface | Agent Card explicitly defines inputs, outputs, and skills |
| Idempotent Tasks | Task results should be the same regardless of retries |
| Graceful Degradation | Agents should handle downstream failures and provide partial results |
| Observable | Structured logging, tracing, and metrics for every agent call |
| Stateless Agents | Keep agents stateless — use external state/checkpointing |
| Concern | Recommendation |
|---|---|
| Framework | LangGraph for complex workflows, ADK for Google-first, CrewAI for teams |
| Tool Access | MCP servers for databases, APIs, file systems |
| Agent Comms | A2A for inter-agent, with SSE streaming |
| State | External checkpointing (Postgres, Redis) — never in-memory only |
| Human-in-the-loop | LangGraph interrupts for critical decisions |
| Error Handling | Retry with exponential backoff, circuit breakers, dead-letter queues |
| Monitoring | OpenTelemetry traces, custom agent metrics (task latency, success rate) |
| Deployment | Containerized (Docker), behind API gateway with auth |
| Practice | Why |
|---|---|
| Version your Agent Cards | Consuming agents may cache cards — version bumps signal changes |
| Use input-required state | Ask for clarification rather than guessing wrong |
| Set reasonable timeouts | Long tasks should support cancellation and resumption |
| Include examples in skills | Help other agents understand expected input/output format |
| Stream by default | Users and calling agents expect real-time feedback |
| Anti-Pattern | Problem | Solution |
|---|---|---|
| God Agent | One agent does everything | Split into specialized agents |
| Tight Coupling | Agents depend on internal knowledge of each other | Use Agent Cards for discovery |
| No Timeouts | Tasks hang forever | Set per-task deadlines and cancellation |
| Synchronous-Only | No streaming support | Always implement SSE streaming |
| Ignoring Errors | Silent failures cascade | Handle errors explicitly, propagate to caller |