a2a-protocol-patterns
暂无简介
- License 许可
- Apache-2.0
- 最近更新
- 2026-11-14
- Stars
- ★ 13
- Forks
- 2
03 SKILL.md 正文
/a2a-protocol-patterns
When to Use
- Cross-organization agent calls: your agent calls an agent at another company/system
- Building a discoverable agent endpoint that any A2A-compatible client can invoke
- Replacing bespoke agent-to-agent HTTP contracts with a standard protocol
- Multi-agent systems where subagents are independent services (LangGraph, CrewAI, AutoGen)
Do NOT use for
- Tool use within a single agent (use MCP — [[mcp-server-patterns]])
- Internal function calls between co-located agents in the same process
- Synchronous tool calls where task lifecycle overhead isn't worth it
MCP vs A2A — the split
MCP (Model Context Protocol) — agent ↔ tool
vertical: agent reads/writes to a tool server
stateless by default, JSON-RPC
A2A (Agent-to-Agent Protocol) — agent ↔ agent
horizontal peer: both sides are agents with reasoning
stateful (task lifecycle), async by default
Production pattern: use both.
Agent A —[A2A]→ Agent B —[MCP]→ tools on Agent B's side
Agent Card (discovery at /.well-known/agent.json)
// Agent Card spec — publish at /.well-known/agent.json
interface AgentCard {
name: string;
version: string;
skills: string[]; // e.g. ["code-review", "security-scan"]
endpoints: {
tasks: string; // POST /tasks
};
auth: {
type: "bearer" | "mtls" | "signed";
scopes?: string[]; // OAuth scopes if bearer
};
modalities: ("text" | "structured" | "image" | "video" | "audio")[];
description?: string;
}
// Example
const yamtamAgentCard: AgentCard = {
name: "yamtam-security-agent",
version: "1.0.0",
skills: ["red-team-check", "blue-team-fix", "leak-check"],
endpoints: { tasks: "https://agents.example.com/tasks" },
auth: { type: "bearer", scopes: ["agent:invoke"] },
modalities: ["text", "structured"],
};
Task lifecycle
submitted → working → completed
→ failed
→ canceled
// Task model
interface A2ATask {
id: string;
skill: string;
input: Record<string, unknown>;
state: "submitted" | "working" | "completed" | "failed" | "canceled";
progress?: number; // 0–100
artifacts?: Artifact[];
error?: string;
}
interface Artifact {
type: "text" | "structured" | "image" | "video" | "audio";
content: string; // text/JSON inline or file path
mimeType?: string;
}
Minimal A2A server (Node.js / Express)
import express from "express";
import { randomUUID } from "crypto";
const app = express();
const tasks = new Map<string, A2ATask>();
// Discovery
app.get("/.well-known/agent.json", (req, res) => res.json(yamtamAgentCard));
// Submit task
app.post("/tasks", express.json(), async (req, res) => {
const task: A2ATask = {
id: randomUUID(),
skill: req.body.skill,
input: req.body.input,
state: "submitted",
};
tasks.set(task.id, task);
res.status(201).json({ task_id: task.id, state: task.state });
// Process async
processTask(task);
});
// Poll for status
app.get("/tasks/:id", (req, res) => {
const task = tasks.get(req.params.id);
if (!task) return res.status(404).json({ error: "not found" });
res.json(task);
});
// SSE for streaming updates
app.get("/tasks/:id/events", (req, res) => {
const task = tasks.get(req.params.id);
if (!task) return res.status(404).end();
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
const send = (data: object) => res.write(`data: ${JSON.stringify(data)}\n\n`);
const interval = setInterval(() => {
const t = tasks.get(req.params.id)!;
send({ state: t.state, progress: t.progress });
if (t.state === "completed" || t.state === "failed") {
clearInterval(interval);
res.end();
}
}, 500);
});
async function processTask(task: A2ATask) {
task.state = "working";
task.progress = 0;
// ... run skill logic ...
task.state = "completed";
task.artifacts = [{ type: "text", content: "Scan complete. 0 critical findings." }];
}
A2A client (discovery + task submission)
async function callAgent(agentBaseUrl: string, skill: string, input: object): Promise<Artifact[]> {
// 1. Discover
const card = await fetch(`${agentBaseUrl}/.well-known/agent.json`).then(r => r.json());
if (!card.skills.includes(skill)) throw new Error(`Agent does not support skill: ${skill}`);
// 2. Submit
const { task_id } = await fetch(card.endpoints.tasks, {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${getToken()}` },
body: JSON.stringify({ skill, input }),
}).then(r => r.json());
// 3. Poll until done
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 1000));
const task: A2ATask = await fetch(`${agentBaseUrl}/tasks/${task_id}`).then(r => r.json());
if (task.state === "completed") return task.artifacts ?? [];
if (task.state === "failed") throw new Error(`Task failed: ${task.error}`);
}
throw new Error("Task timed out");
}
Auth patterns
Bearer token — OAuth2 or opaque; declare required scopes in Agent Card
mTLS — mutual TLS; both sides present certificates; for cross-org zero-trust
Signed request — HMAC-SHA256 over request body; lightweight; no PKI required
Anti-Fake-Pass Checklist
❌ No Agent Card → client can't discover capabilities; bespoke integration required
❌ Task state not persisted → server restart loses in-progress tasks
❌ No auth on /tasks endpoint → anyone can invoke any skill
❌ Synchronous /tasks POST that blocks until done → timeouts on long skills; use async + poll/SSE
❌ Using A2A for tool calls within one agent → MCP is the right layer; A2A overhead unwarranted
❌ Opaque lifecycle violated → prescribing HOW remote agent solves the task defeats the abstraction
04 同仓库更多 Skills
openai--sentry--sentry
Use when the user asks to inspect Sentry issues or events, summarize recent production errors, or pull basic Sentry health data via the Sentry API; perform read-only queries with the bundled script and require `SENTRY_AUTH_TOKEN`.
ito-basket-compare
Compare Itô prediction-market baskets against a user's knowledge base, portfolio notes, financial context, watchlist, or research thesis. Use for read-only basket comparison and gap analysis without investment advice or live trading.
implementing-network-traffic-baselining
Build network traffic baselines from NetFlow/IPFIX data using Python pandas for statistical analysis, z-score anomaly detection, and hourly/daily traffic pattern profiling
detecting-evasion-techniques-in-endpoint-logs
Detects defense evasion techniques used by adversaries in endpoint logs including log tampering, timestomping, process injection, and security tool disabling. Use when investigating suspicious endpoint behavior, building detection rules for evasion tactics, or conducting threat hunting for stealthy adversary activity. Activates for requests involving evasion detection, defense evasion analysis, log tampering detection, or MITRE ATT&CK TA0005.
implementing-microsegmentation-with-guardicore
Implementing microsegmentation using Akamai Guardicore Segmentation to map application dependencies, create granular network policies, visualize east-west traffic flows, and enforce least-privilege communication between workloads across data centers and cloud.
ramdisk-tmpfs-patterns
暂无简介