1️⃣ Introduction
Agent-to-Agent (A2A) Protocol is an open standard that enables independent AI agents to discover each other, share capabilities, and collaborate on tasks in a secure and interoperable way. Instead of building one monolithic agent, A2A allows specialized agents—such as a planner, researcher, or executor—to communicate seamlessly across different frameworks and organizations. By defining a common structure for discovery (Agent Cards), task management (Task lifecycle), and communication (messages & parts), A2A provides the foundation for scalable, multi-agent ecosystems where agents can work together much like microservices do in modern software architectures.
2️⃣ Agent Cards
- A small, self-describing JSON document that advertises an agent’s identity, capabilities, and how to interact with it.
- It typically lives at a well-known URL like
https://yourdomain.com/.well-known/agent.json(oragent-card.json). - It enables automated discovery and interoperability so other agents can safely submit tasks and receive updates without custom integrations.
- A consuming agent fetches and parses the card → learns endpoints, formats, and auth → submits tasks accordingly.
🔹 Agent Card Keys
id
- A globally unique identifier (URN/UUID) for the agent (e.g.,
urn:agent:example:researcher-1).
name
- Human-readable name for UIs and logs.
description
- Short summary of the agent’s purpose and domain.
version
- Semantic version of the agent service; helps with change management and client compatibility.
endpoints/task_submit
- HTTP endpoint where other agents POST tasks for execution.
- Accepts a task object (JSON). Returns task acceptance/ID and may start processing asynchronously.
endpoints/events
- Endpoint to stream progress updates (SSE/webhooks) or poll for status/results.
- Clients subscribe or query using the previously returned task ID.
capabilities
- A list describing actions/skills (e.g.,
web.search,summarize). - Lets peers quickly assess whether this agent can fulfill a requested task.
modalities
- Supported input/output formats (e.g.,
text/plain,application/json). - Ensures payload compatibility between agents.
auth
- Required authentication scheme(s) (e.g., OAuth2 scopes, mTLS, API keys).
- Enforces secure, auditable access aligned with enterprise policies.
skills (optional)
- Richer, structured descriptions of capabilities with tags and examples.
- Improves automated routing/selection among multiple candidate agents.
protocolVersion (optional)
- The A2A protocol version implemented.
- Helps clients negotiate behavior and avoid drift.
🔹 Example Agent Card
{
"a2a_version": "1.0",
"id": "urn:agent:example:researcher-1",
"name": "Researcher Agent",
"description": "Finds sources on the web and summarizes them.",
"version": "1.0.0",
"endpoints": {
"task_submit": "https://researcher.example.com/a2a/tasks",
"events": "https://researcher.example.com/a2a/events"
},
"capabilities": ["web.search", "summarize"],
"modalities": ["text/plain", "application/json"],
"auth": {
"type": "oauth2",
"scopes": ["a2a.tasks.write", "a2a.events.read"]
}
}
3️⃣ Task Submission (A2A)
🔹 Key Points
- Submit work to another agent via its
task_submitendpoint (from the Agent Card).
Async-first: server returns immediately with{ id, status: "submitted", links: { self, events } }.- Track progress using events (SSE/webhook) for real-time updates until terminal status:
completedorfailed. - Use a client-generated task ID for idempotency; retries with the same ID should not duplicate execution.
- Final output is received via the events stream.
🔹 Example Flow (High-Level)
- Discover receiver’s
task_submitfrom its Agent Card. - Build task payload:
id,requester, andpayload(type+ args).
POSTit totask_submit→ receive async ack withlinks.events.- Subscribe to the events endpoint to get status updates and results.
- Print the final status and artifacts when the task is completed.
🔹 Example Task Submit in Python (Async with SSE)
# Brief, happy-path example: async task submission + SSE event subscription
# Focused on clarity, with inline comments explaining each step.
import asyncio, json, uuid, httpx
# Endpoint for submitting tasks — discovered from the Agent Card
TASK_SUBMIT_URL = "https://receiver.example.com/a2a/tasks"
# Access token (OAuth2 bearer, API key, or other scheme from Agent Card auth section)
ACCESS_TOKEN = "<TOKEN>"
async def main():
# Step 1: Generate a unique task ID for idempotency
# Using UUID ensures retries with the same ID won't duplicate execution if the server deduplicates
task_id = f"task-{uuid.uuid4()}"
# Step 2: Build the payload
# Includes:
# - id: chosen by the client
# - requester: who is submitting (URN or URL)
# - payload: actual work request (type + arguments)
payload = {
"id": task_id,
"requester": "urn:agent:example:planner-1",
"payload": {
"type": "web.search",
"query": "Latest AI conferences in 2025"
}
}
async with httpx.AsyncClient() as client:
# Step 3: Submit the task
# POST returns quickly with async acknowledgment (id, status=submitted, links)
ack = (await client.post(
TASK_SUBMIT_URL,
headers={
"Authorization": f"Bearer {ACCESS_TOKEN}", # auth as required by Agent Card
"Accept": "application/json" # we want JSON back
},
json=payload,
)).json()
print("Submitted", ack["id"], "status=", ack["status"])
# ack contains "links": { "self": ..., "events": ... }
# - links.self: poll for updates
# - links.events: subscribe for streaming updates (preferred)
# Step 4: Subscribe to events stream (SSE)
# Server sends progress + final results as "data: {...}" lines
events_url = ack["links"]["events"]
async with client.stream(
"GET",
events_url,
headers={
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Accept": "text/event-stream"
}
) as resp:
# Loop over incoming SSE lines until we see a terminal status
async for line in resp.aiter_lines():
if not line or not line.startswith("data:"):
continue # ignore comments/keepalives
evt = json.loads(line[5:].strip()) # strip "data:" prefix, parse JSON
if "status" in evt:
print("[event] status=", evt["status"])
# Break once we hit completed/failed — final output is available
if evt["status"] in {"completed", "failed"}:
final = evt
break
else:
# Could be partial result or log message
print("[event]", evt)
# Step 5: Print final output
print("Final status:", final["status"])
for a in final.get("artifacts", []):
# Artifacts may have inline content (text) or links (href)
print("-", a.get("type"), a.get("content", a.get("href", "<no content>")))
if __name__ == "__main__":
asyncio.run(main())
🔹 Example Output
Submitted: {"id": "task-123", "status": "submitted", "links": {"events": "..."}}
[event] {"status": "working"}
[event] {"status": "completed", "artifacts": [{"type": "text/plain", "content": "Upcoming AI conferences: NeurIPS 2025, ICML 2025..."}]}
Final output: {"status": "completed", "artifacts": [{"type": "text/plain", "content": "Upcoming AI conferences: NeurIPS 2025, ICML 2025..."}]}
4️⃣ Messages & Parts
🔹 Key Points
- Messages are a general-purpose communication channel between agents, outside of task submission.
- Each message has metadata (id, sender, recipient, timestamp) and a list of parts.
- Typed payloads such as text, JSON, image, or file references. Each part has a
typeand eithercontentorhref. - Share context, logs, prompts, human-in-the-loop requests, or supporting artifacts.
- Messages are POSTed to the
messagesendpoint advertised in the Agent Card. - Typed parts let heterogeneous agents parse what they understand and ignore the rest.
🔹 Example Flow
- Agent A POSTs a message to Agent B’s
messagesendpoint. - The message contains metadata plus one or more typed parts.
- Agent B processes each part as appropriate (display, parse JSON, fetch URI, etc.).
🔹 Example Message (JSON)
{
"id": "msg-42",
"sender": "urn:agent:example:planner-1",
"recipient": "urn:agent:example:researcher-1",
"timestamp": "2025-08-28T12:00:00Z",
"parts": [
{
"type": "text/plain",
"content": "Please summarize this document."
},
{
"type": "application/json",
"content": { "docId": "abc123", "priority": "high" }
},
{
"type": "text/uri-list",
"href": "https://example.com/docs/abc123.pdf"
}
]
}
🔹 Example Server Response
{
"id": "msg-3f1e3f7b-2c58-42ab-94cd-fc22e3b1687a",
"status": "ok",
"received_at": "2025-08-28T12:34:56Z",
"echo": {
"parts": [
{ "type": "text/plain", "content": "Please summarize this document." },
{ "type": "text/uri-list", "href": "https://example.com/docs/abc123.pdf" }
]
}
}
SOCIAL SHARE CARD GENERATOR