#MCP / A2A / Tool Schema 专项强化题库(第十五批:Agent 协议与工具调用设计)
#一、高频问题速览
| 编号 | 问题 | 核心考点 |
|---|---|---|
| 277 | MCP 的核心架构(Host-Client-Server)和三类原语是什么? | 协议层、工具/资源/提示、JSON-RPC |
| 278 | A2A 协议与 MCP 协议的定位差异是什么?何时组合使用? | Agent 协作 vs 工具调用、任务生命周期、互补性 |
| 279 | Function Calling 的 Tool Schema 设计有哪些关键原则? | JSON Schema、去歧义、枚举约束、示例与版本 |
| 280 | MCP 中的工具审批(require_approval)和 OAuth 认证机制为什么重要? | 最小权限、可审计、人机在环 |
| 281 | 多 agent 系统中如何避免 token/配额耗尽的连锁失败? | 集中限流、指数退避、配额预留、缓存 |
| 282 | A2A 的 Agent Card 包含哪些信息?能力发现流程是怎样的? | well-known、能力声明、认证方式、动态发现 |
| 283 | 中心化 Orchestrator vs Mesh/P2P 多 agent 架构如何选型? | 治理一致性 vs 弹性容错、职责边界、审计链 |
| 284 | 如何为带副作用的工具调用设计幂等性和错误恢复机制? | Idempotency-Key、checkpoint、断点续传、补偿 |
| 285 | MCP/A2A 场景下的长任务(数小时)应该如何建模? | 任务原语、异步状态流、call-now/fetch-later |
| 286 | Tool Schema 的错误返回结构应该包含哪些字段?如何区分 transient 与 permanent 错误? | 结构化错误、Retry-After、状态码、降级策略 |
#二、逐题详细解答
#277. MCP 的核心架构(Host-Client-Server)和三类原语是什么?
#知识点
- MCP(Model Context Protocol)
- Host-Client-Server 架构
- Tools / Resources / Prompts
- JSON-RPC 2.0
#详细解答
MCP 的定位:
MCP(Model Context Protocol)是由 Anthropic 推动的开放标准协议,目标是标准化 LLM/Agent 与外部工具、数据源之间的交互,减少 N×M 的集成复杂度。
核心架构(Host-Client-Server):
- Host:承载 AI 交互的应用程序(如 Claude Desktop、Cursor、IDE 插件)。Host 负责协调多个 Client。
- Client:每个 MCP Server 在 Host 内对应一个 Client,负责与 Server 建立连接、发现能力、转发请求。
- Server:暴露具体能力的服务端(如文件系统、数据库查询、GitHub API、代码执行器)。
Host 与 Client/Server 之间通过持久连接交互,传输层支持 STDIO、SSE、WebSocket、Streamable HTTP 等。消息格式基于 JSON-RPC 2.0。
三类原语:
- Tools(工具):模型可以调用的函数/动作,带有结构化参数定义(JSON Schema)。例如
search_web、execute_code、send_email。工具调用可能产生副作用。 - Resources(资源):只读的数据上下文,供模型参考但不产生副作用。例如文件内容、数据库 schema、API 文档。Resources 可以通过静态 URI 或模板化 URI 访问。
- Prompts(提示模板):预定义的提示模板,帮助模型更好地完成特定任务。例如 "请以 JSON 格式总结以下文档"。
工程意义:MCP 把"模型需要什么能力"和"能力怎么实现"解耦,让应用开发者只需对接 MCP Client,而工具提供者只需实现 MCP Server。
#278. A2A 协议与 MCP 协议的定位差异是什么?何时组合使用?
#知识点
- A2A(Agent-to-Agent)
- MCP(Model Context Protocol)
- 任务生命周期 vs 工具调用
- 协议互补性
#详细解答
定位差异:
| 维度 | MCP | A2A |
|---|---|---|
| 核心目标 | 标准化 Agent/应用对外部工具、资源的调用 | 标准化 Agent 之间的发现、协作与任务委派 |
| 交互粒度 | 离散的工具调用(request-response) | 状态化的任务生命周期(pending → working → completed) |
| 连接对象 | Agent ↔ Tool/Data | Agent ↔ Agent |
| 状态管理 | 通常无状态,结果直接返回 caller | 天然状态化,支持异步更新与流式推送 |
| 能力发现 | Server 在连接时暴露 tools/resources 清单 | Agent Card 在 /.well-known/agent.json 公开能力与认证要求 |
MCP 适合的场景:
- 单个 Agent 需要调用具体工具(搜索、数据库、代码执行、邮件发送)。
- 需要集中化的工具治理、参数验证、审批与审计。
A2A 适合的场景:
- 多个 Agent 之间需要协作完成复杂任务(如 Planner Agent 委派给 Researcher Agent)。
- 需要长期运行、分步协商、状态流式更新的工作流。
- 需要跨系统的 Agent 发现与能力协商。
组合使用:
典型架构中,A2A 负责高层协调与任务分配,MCP 负责具体执行:
- Planner Agent 通过 A2A 发现 Researcher Agent 的能力。
- Planner 通过 A2A 提交任务。
- Researcher Agent 内部通过 MCP 调用搜索引擎、数据库、代码执行器等工具完成子任务。
- Researcher 通过 A2A 的 task lifecycle 向 Planner 汇报进度与结果。
#279. Function Calling 的 Tool Schema 设计有哪些关键原则?
#知识点
- JSON Schema
- 去歧义命名
- 枚举约束
- 示例与文档
- 版本管理
#详细解答
Function Calling 的核心是让 LLM 根据结构化 schema 生成可执行的工具调用。Schema 设计的好坏直接决定工具调用的准确率。
关键设计原则:
1. 严格的 JSON Schema 结构
- 根类型必须是
"type": "object"。 - 每个参数都要有
"type"、"description",复杂类型用嵌套对象。 - 用
"required"明确必填字段,用"enum"限制取值范围。
2. 去歧义命名与描述
- 参数名要具体:
user_id比user好,start_date比date1好。 - 描述要简洁但包含约束和示例:"城市名或经纬度,例如 'Shanghai' 或 '31.23,121.47' "。
3. 枚举约束减少幻觉
- 对于有限选项(如温度单位
celsius/fahrenheit、排序方式asc/desc),务必使用enum。 - 这能显著降低模型生成非法参数的概率。
4. 提供调用示例与错误示例
- 在 schema 或系统提示中给出典型调用示例,帮助模型理解期望格式。
- 同时给出错误示例(如缺少必填字段、类型不匹配),让模型学会规避常见错误。
5. 版本化与向后兼容
- 工具 schema 应该带有版本号(如
v1、v2)。 - 添加字段是兼容变更,删除/修改已有字段语义是不兼容变更。
- 旧版本应保留兼容转换层,避免已部署的 Agent 突然失效。
6. 输出/错误 schema 也要结构化
- 不仅输入要结构化,工具返回也应包含
status、code、message、data四元结构,方便上层 Agent 做程序化判断。
#280. MCP 中的工具审批(require_approval)和 OAuth 认证机制为什么重要?
#知识点
- 最小权限原则(Least Privilege)
- 人机在环(Human-in-the-loop)
- OAuth 2.1 / PKCE
- 审计链
#详细解答
工具审批(require_approval)的重要性:
MCP 规范支持为敏感工具(如发送邮件、转账、删除文件、修改数据库)设置 require_approval 标志。这意味着模型生成调用意图后,必须先获得人类用户或上层系统的显式批准,才能实际执行。
为什么重要:
- 防止自主 Agent 的失控行为:Agent 可能因 prompt 注入、逻辑错误或恶意输入而调用危险工具。
- 满足合规要求:金融、医疗等行业对"自动执行敏感操作"有严格的人机协同要求。
- 建立信任:用户需要知道 Agent 打算做什么,并有权拒绝。
OAuth 认证机制的重要性:
MCP 规范推荐使用 OAuth 2.1 + PKCE 作为认证模式,而不是简单的 API key 或共享 secret。
相比 API key 的优势:
- 可撤销:token 有过期时间,泄露后可被吊销,影响范围可控。
- 权限范围可控:OAuth scope 能精确限制 Agent 能访问哪些资源、执行哪些操作。
- 审计链完整:OAuth 流程能关联"human identity → agent identity → tool call",满足企业审计需求。
- 跨域安全:PKCE 防止 authorization code 拦截攻击,适合桌面/移动 Host 场景。
工程建议:在生产级 MCP 部署中,务必在网关层强制执行 OAuth,而不是依赖本地无认证的 Server。
#281. 多 agent 系统中如何避免 token/配额耗尽的连锁失败?
#知识点
- 速率限制(Rate Limiting)
- 指数退避(Exponential Backoff)
- 配额预留与配额池
- 缓存策略
- Retry Storm
#详细解答
问题描述:
在多 Agent 系统中,一个上层 Agent 可能同时触发多个下层 Agent 或工具调用,形成调用级联。如果没有限流机制,很容易出现:
- API 配额瞬间耗尽。
- 费用激增(runaway agent)。
- 下游服务被压垮,引发级联故障(Retry Storm)。
缓解策略:
1. 集中配额管理与预留
- 在网关或 Orchestrator 层维护统一的配额池(如 Redis)。
- 为高优先级任务预留额度,低优先级任务受限制。
- 实时监控每个 Agent/Task 的 token/调用消耗。
2. 网关层限流(429 + Retry-After)
- 当调用超过阈值时,网关返回 HTTP 429 并附带
Retry-After头。 - Agent 端必须尊重这个响应,而不是盲目重试。
3. Agent 端指数退避与抖动(Jitter)
- 遇到 429 或 5xx 时,采用指数退避:
wait = base * 2^attempt + random_jitter。 - 抖动能避免多个 Agent 在同一时刻重试,造成新的流量峰值。
4. 结果缓存
- 对于重复或相似的查询(如频繁检索同一份文档),在 Agent 层或 MCP Client 层引入缓存(如向量缓存、语义去重缓存)。
- 缓存命中能直接减少下游调用。
5. 任务分解与批处理
- 把一个大任务拆成多个子任务时,评估是否可以把某些子任务合并批处理,减少总调用次数。
#282. A2A 的 Agent Card 包含哪些信息?能力发现流程是怎样的?
#知识点
- Agent Card
/.well-known/agent.json- 能力发现(Capability Discovery)
- 认证方案声明
#详细解答
Agent Card 是什么:
Agent Card 是 A2A 协议中的能力声明文件,托管在 Agent 的 /.well-known/agent.json 路径下。其他 Agent 或系统可以通过标准 HTTP GET 请求读取这个文件,从而了解该 Agent 能做什么、需要什么认证、端点在哪里。
典型 Agent Card 内容:
{
"agent_id": "researcher-v1",
"name": "Researcher Agent",
"description": "擅长网络搜索、文献综述与数据整理",
"capabilities": ["web_research", "summarization", "data_extraction"],
"auth": {
"schemes": ["oauth2", "bearer_token"]
},
"endpoints": {
"tasks": "https://agent.example.com/tasks",
"status": "https://agent.example.com/status",
"events": "https://agent.example.com/events"
},
"rate_limits": {
"max_requests_per_minute": 60
}
}
关键字段:
capabilities:该 Agent 支持的任务类型列表。auth.schemes:支持的认证方式(OAuth、Bearer、API key、mTLS 等)。endpoints:任务提交、状态查询、事件订阅的 URL。rate_limits:可选的速率限制声明。
能力发现流程:
- 发现阶段:委派方 Agent 向目标域名发送
GET /.well-known/agent.json。 - 协商阶段:解析 Agent Card,确认目标 Agent 是否具备所需能力,以及委派方是否满足认证要求。
- 认证阶段:按 Agent Card 声明的方式获取 access token。
- 任务委派阶段:向
endpoints.tasks提交任务,获得task_id。 - 状态跟踪阶段:通过
endpoints.status或 SSE 事件流跟踪任务进展,直到 completed/failed。
#283. 中心化 Orchestrator vs Mesh/P2P 多 agent 架构如何选型?
#知识点
- Orchestrator-Worker 架构
- Mesh / P2P 协作
- 一致性 vs 弹性
- 审计链与治理
- 故障隔离
#详细解答
中心化 Orchestrator 架构:
- 结构:一个中心化的 Planner/Orchestrator 负责任务分解、路由选择、结果聚合和错误恢复;多个 Worker Agent 负责执行具体子任务。
- 优点:
- 易于实现全局一致性、状态同步和审计追踪。
- Orchestrator 可以集中控制权限、配额和审批流程。
- 调试和故障排查更容易(所有决策在一个节点)。
- 缺点:
- Orchestrator 是单点瓶颈,高并发时可能成为性能瓶颈。
- 系统弹性受限于 Orchestrator 的可用性。
Mesh / P2P 架构:
- 结构:Agent 之间点对点直接通信,没有中心化协调者。任务通过广播、协商或共识机制分配。
- 优点:
- 高弹性,单个 Agent 故障不会影响全局。
- 更容易水平扩展。
- 缺点:
- 冲突解决、状态一致性、全局审计非常复杂。
- 需要复杂的发现、协商和共识机制。
选型建议:
- 企业级/金融/医疗:优先选中心化 Orchestrator,因为治理、审计、合规是首要需求。
- 高并发/弹性优先的互联网产品:可采用分层混合架构——顶层用轻量级 Orchestrator 做路由和监控,子域内用 Mesh 协作。
- 快速原型/内部工具:先用中心化 Orchestrator,业务跑通后再考虑解耦。
最佳实践:即使使用 Mesh,也建议在关键路径上保留一个"审计协调者",用于记录任务来源链和最终状态,而不是完全去中心化。
#284. 如何为带副作用的工具调用设计幂等性和错误恢复机制?
#知识点
- 幂等性(Idempotency)
- Idempotency-Key
- Checkpoint 与断点续传
- 补偿事务(Compensation)
- Temporal / Workflow 模式
#详细解答
为什么幂等性至关重要:
Agent 在执行工具调用时,可能因网络超时、服务降级或自身重试策略而多次调用同一个工具。如果工具带有副作用(如扣款、发送邮件、创建订单),重复执行会导致灾难性后果。
幂等性设计原则:
1. 幂等键(Idempotency-Key)
- 每次工具调用时,Agent 生成一个全局唯一的
Idempotency-Key(如uuid)并随请求发送。 - 工具服务端记录已处理的 Key,如果收到重复的 Key,直接返回上一次的结果,而不是重新执行。
- Key 应该关联到
task_id和agent_id,便于审计。
2. 工作流级 Checkpoint
- 使用 Temporal、Cadence 或自研工作流引擎,在每个步骤成功后持久化 checkpoint。
- 如果流程中断,可以从上一个 checkpoint 恢复,而不是从头重试所有步骤。
- 已完成且带有副作用的步骤不会被重复执行。
3. 错误分类与恢复策略
- Transient 错误(网络抖动、429 限流、超时):应该重试,配合指数退避。
- Permanent 错误(参数校验失败、权限不足、业务规则冲突):应该快速失败,记录错误,并触发人工介入或回退计划。
4. 补偿事务(Saga 模式)
- 对于多步骤的复杂事务,如果某一步永久失败,需要执行补偿操作来撤销已完成的副作用步骤。
- 例如:已创建订单 → 支付失败 → 执行补偿:取消订单、释放库存。
5. 状态机显式建模
- 把工具调用建模为状态机:
pending → in_progress → succeeded / failed / compensated。 - 只有从
pending状态才能进入in_progress,防止并发下的重复执行。
#285. MCP/A2A 场景下的长任务(数小时)应该如何建模?
#知识点
- 异步任务生命周期
- Task 原语
- call-now / fetch-later 模式
- SSE(Server-Sent Events)
- 超时与撤销
#详细解答
为什么长任务需要特殊建模:
MCP 的标准工具调用是 request-response 语义,同步等待数小时不现实(HTTP 超时、连接断开、Agent 状态丢失)。A2A 和 MCP 扩展都提供了对长任务的支持。
MCP 中的长任务建模(SEP-1686 / Task 原语):
MCP 扩展引入了 Task 原语,支持 call-now / fetch-later 模式:
- Agent 发起工具调用请求,Server 立即返回一个
task_id,而不等待实际执行完成。 - Agent 可以定期用
task_id查询任务状态(polling),或通过 SSE 订阅状态更新。 - 任务完成后,Agent 再 fetch 最终结果。
A2A 中的长任务建模:
A2A 把 Task 作为一级实体,任务天然带有状态机:
pending → working → completed / failed / canceled
- 委派方提交任务后,接收方返回
202 Accepted和task_id。 - 在工作过程中,接收方通过 SSE 或 HTTP 回调发送进度更新(
working、partial_result)。 - 委派方可以发送取消请求,接收方应支持优雅终止。
工程最佳实践:
- 显式超时与撤销策略:任务提交时应声明
timeout和cancellation_policy。 - 权限续签:长时间任务中,access token 可能过期,需要设计 token 刷新或续签机制。
- Checkpoint 持久化:执行端应定期保存进度,支持从断点恢复。
- 结果保留期:声明任务结果的保留时间(TTL),过期后自动清理,避免存储无限增长。
#286. Tool Schema 的错误返回结构应该包含哪些字段?如何区分 transient 与 permanent 错误?
#知识点
- 结构化错误返回
- Transient vs Permanent 错误
- Retry-After
- 降级策略(Graceful Degradation)
- 错误示例与文档
#详细解答
推荐的错误返回结构:
工具返回应始终使用结构化格式,至少包含以下字段:
{
"status": "error",
"code": "RATE_LIMIT_EXCEEDED",
"message": "API 调用次数超过每分钟 60 次的限制",
"details": {
"retry_after": 30,
"limit": 60,
"window": "1m"
},
"request_id": "req_abc123"
}
字段说明:
status:success或error,方便上层快速判断。code:机器可读的错误码,如INVALID_PARAMETER、RATE_LIMIT_EXCEEDED、PERMISSION_DENIED、INTERNAL_ERROR。message:人类可读的错误描述,供 Agent 理解或展示给用户。details:额外的结构化信息,如retry_after、缺失字段列表、权限范围等。request_id:用于日志追溯和故障排查。
Transient 与 Permanent 错误的区分:
| 类型 | 特征 | 典型 HTTP 状态码 | 应对策略 |
|---|---|---|---|
| Transient | 临时性问题,重试可能成功 | 429、502、503、504 | 指数退避后重试,读取 Retry-After |
| Permanent | 请求本身有问题,重试不会成功 | 400、401、403、404、422 | 快速失败,记录错误,触发降级或人工介入 |
工程建议:
- 工具层显式标注错误类型:在
code或details.error_type中明确标注"transient": true/false。 - Agent 层根据类型选择策略:
- Transient:重试最多 N 次,每次退避时间递增。
- Permanent:立即停止当前路径,尝试替代工具或向用户汇报失败原因。
- 降级策略(Graceful Degradation):如果主工具永久失败,是否有备用工具?例如:主搜索引擎 403 时,切换到本地索引或简化查询。
- 文档中必须包含错误示例:在 Tool Schema 文档中为每个工具提供至少一个错误返回示例,帮助 Agent 学会正确解析和处理。