# MAMP:Minimal Agent Message Protocol **更新日期:** 2026-03-04 ## 设计目标 实现与**其他 Agent 系统**(非本系统)的通用交互接口,保持最简化原则。 **与现有方案的关系**: - [A2A 跨设备通信](./a2a-cross-device.md):内部 Agent 间通信(基于 Trace API) - **MAMP 协议**(本文档):与外部 Agent 系统的通用交互 --- ## 核心设计原则 1. **最小化协议**:只定义消息信封,不管内容格式 2. **适配器模式**:通过适配器层与内部系统集成 3. **松耦合**:各家 Agent 保持独立实现 4. **渐进式**:先实现基础功能,需要时再扩展 --- ## 消息格式 ### 基础消息结构 ```json { "protocol": "mamp/1.0", "message_id": "msg-uuid-123", "conversation_id": "conv-uuid-456", "from": "agent://your-domain.com/agent-123", "to": "agent://other-domain.com/agent-456", "content": [...], "metadata": { "timestamp": "2026-03-04T10:00:00Z" } } ``` ### 字段说明 | 字段 | 类型 | 必需 | 说明 | |------|------|------|------| | `protocol` | string | 是 | 协议版本标识 | | `message_id` | string | 是 | 消息唯一标识 | | `conversation_id` | string | 否 | 对话标识(不提供则新建对话) | | `from` | string | 是 | 发送方 Agent URI | | `to` | string | 是 | 接收方 Agent URI | | `content` | string/array | 是 | 消息内容(支持多模态) | | `metadata` | object | 是 | 元数据(时间戳等) | ### 新建 vs 续跑 **规则**:通过 `conversation_id` 字段判断 - **无 `conversation_id`**(null 或不存在)→ 新建对话,接收方生成并返回 conversation_id - **有 `conversation_id`** → 续跑对话,接收方查找对应的内部 trace_id **conversation_id 与 trace_id 的关系**: - `conversation_id`:跨 Agent 的对话标识符,双方共享 - `trace_id`:每个 Agent 内部的执行记录,各自独立 - 每个 Agent 维护 `conversation_id → trace_id` 映射 --- ## 多模态内容格式 ### Content 结构 参考 Anthropic SDK 和现有多模态实现(`agent/docs/multimodal.md`): ```json { "content": [ { "type": "text", "text": "这是文本内容" }, { "type": "image", "source": { "type": "url", "url": "https://...", "media_type": "image/png" } }, { "type": "image", "source": { "type": "base64", "media_type": "image/jpeg", "data": "base64..." } }, { "type": "code", "language": "python", "code": "def hello(): pass" }, { "type": "file", "name": "report.pdf", "mime_type": "application/pdf", "source": { "type": "url", "url": "https://..." } } ] } ``` ### 纯文本简写 ```json { "content": "纯文本消息" } ``` 等价于: ```json { "content": [{"type": "text", "text": "纯文本消息"}] } ``` --- ## Agent Card(身份与能力) 每个 Agent 提供静态的 card 端点,用于身份识别和能力发现。 ### 端点 ``` GET https://your-agent.com/mamp/v1/card ``` ### 响应格式 ```json { "protocol": "mamp/1.0", "agent_id": "agent://your-domain.com/agent-123", "name": "Code Analyst", "description": "专注于代码分析的 Agent", "owner": { "user_id": "user-789", "user_name": "张三", "organization": "YourCompany" }, "device": { "device_id": "device-mac-001", "device_name": "MacBook Pro", "location": "Beijing Office", "platform": "darwin" }, "capabilities": { "content_types": ["text", "image", "code"], "max_message_size": 10485760, "streaming": true, "async": true, "tools": ["code_analysis", "file_read", "web_search"] }, "access": { "public": false, "allowed_agents": ["agent://trusted.com/*"], "require_auth": true } } ``` --- ## 传输层 ### HTTP REST(最简实现) **发送消息**: ```http POST https://other-agent.com/mamp/v1/messages Content-Type: application/json Authorization: Bearer {api_key} {MAMP 消息体} ``` **响应**: ```json { "conversation_id": "conv-abc-123", "message_id": "msg-xyz-456", "status": "received" } ``` **错误响应**: ```json { "error": "conversation_not_found", "message": "Conversation conv-xxx not found", "status_code": 404 } ``` ### 可选扩展 - **WebSocket**:实时双向通信 - **Server-Sent Events**:流式响应 - **Message Queue**:异步消息(NATS/Redis) --- ## 寻址方案 使用 URI 格式:`agent://domain/agent-id` **示例**: - `agent://your-domain.com/trace-123` - 你的 Agent - `agent://claude.ai/session-456` - Claude - `agent://openai.com/assistant-789` - OpenAI Assistant 每个 Agent 系统自己决定如何解析 `agent-id` 部分。 --- ## 系统集成 ### 三层架构 ``` ┌─────────────────────────────────────────────────┐ │ Layer 3: 内部 Agent 逻辑 │ │ (Trace, Goal, Messages...) │ └─────────────────────────────────────────────────┘ ↕ ┌─────────────────────────────────────────────────┐ │ Layer 2: MAMP 适配器 │ │ - 内部格式 ↔ MAMP 格式转换 │ │ - conversation_id ↔ trace_id 映射 │ └─────────────────────────────────────────────────┘ ↕ ┌─────────────────────────────────────────────────┐ │ Layer 1: 传输层(HTTP/WebSocket/MQ) │ └─────────────────────────────────────────────────┘ ``` ### 接收端实现 **实现位置**:`agent/trace/mamp_api.py` ```python @app.post("/mamp/v1/messages") async def receive_mamp_message(msg: dict): """接收外部 Agent 的 MAMP 消息""" conv_id = msg.get("conversation_id") if not conv_id: # 新建对话 conv_id = f"conv-{generate_uuid()}" # 创建新 Trace async for item in runner.run( messages=[{"role": "user", "content": msg["content"]}], config=RunConfig( context={ "mamp_conversation_id": conv_id, "mamp_from": msg["from"] } ) ): if isinstance(item, Trace): await store_conversation_mapping(conv_id, item.trace_id) return { "conversation_id": conv_id, "message_id": msg["message_id"], "status": "received" } else: # 续跑对话 trace_id = await get_trace_by_conversation_id(conv_id) if not trace_id: raise HTTPException(404, f"Conversation {conv_id} not found") await runner.run( messages=[{"role": "user", "content": msg["content"]}], config=RunConfig(trace_id=trace_id) ) return { "conversation_id": conv_id, "message_id": msg["message_id"], "status": "received" } ``` ### 发送端实现 **实现位置**:`agent/tools/builtin/mamp_adapter.py` ```python @tool(description="与外部 Agent 通信") async def send_to_agent( target_agent: str, message: str, conversation_id: Optional[str] = None, ctx: ToolContext = None ) -> ToolResult: """ 发送消息到外部 Agent Args: target_agent: 目标 Agent URI (agent://domain/id) message: 消息内容 conversation_id: 对话 ID(可选,不提供则新建) """ # 构建 MAMP 消息 mamp_msg = { "protocol": "mamp/1.0", "message_id": generate_uuid(), "from": f"agent://{config.domain}/{ctx.trace_id}", "to": target_agent, "content": message, "metadata": {"timestamp": datetime.now().isoformat()} } if conversation_id: mamp_msg["conversation_id"] = conversation_id # 发送 agent_url = parse_agent_url(target_agent) response = await http_post(f"{agent_url}/mamp/v1/messages", mamp_msg) # 新建时存储映射 if not conversation_id: await store_conversation_mapping( response["conversation_id"], ctx.trace_id ) return ToolResult( title=f"已发送到 {target_agent}", output=f"Conversation ID: {response['conversation_id']}", long_term_memory=f"与 {target_agent} 的对话 {response['conversation_id']}" ) ``` ### conversation_id 映射存储 **实现位置**:`agent/trace/conversation_store.py` ```python class ConversationStore: """管理 MAMP conversation_id 和内部 trace_id 的映射""" def __init__(self, base_dir: str = ".trace"): self.mapping_file = Path(base_dir) / "mamp_conversations.json" async def store_mapping(self, conversation_id: str, trace_id: str): """存储映射关系""" mappings = await self._load_mappings() mappings[conversation_id] = { "trace_id": trace_id, "created_at": datetime.now().isoformat(), "last_message_at": datetime.now().isoformat() } await self._save_mappings(mappings) async def get_trace_id(self, conversation_id: str) -> Optional[str]: """根据 conversation_id 查找 trace_id""" mappings = await self._load_mappings() mapping = mappings.get(conversation_id) return mapping["trace_id"] if mapping else None ``` --- ## 使用示例 ### 新建对话 ```python # 调用外部 Agent result = await send_to_agent( target_agent="agent://other.com/code-analyst", message="帮我分析这段代码的性能" ) # 返回: {"conversation_id": "conv-abc-123", ...} ``` ### 续跑对话 ```python # 继续之前的对话 result = await send_to_agent( target_agent="agent://other.com/code-analyst", message="那如果用异步方案呢?", conversation_id="conv-abc-123" ) ``` ### 多模态消息 ```python # 发送图片 result = await send_to_agent( target_agent="agent://other.com/image-analyst", message={ "content": [ {"type": "text", "text": "分析这张图片"}, { "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": encode_image_base64("screenshot.png") } } ] } ) ``` --- ## 与现有标准的关系 MAMP 可以作为其他标准的"翻译层": - **MCP (Model Context Protocol)** → 写 MCP ↔ MAMP 适配器 - **OpenAI Assistant API** → 写 OpenAI ↔ MAMP 适配器 - **自定义协议** → 写对应的适配器 **核心思想**:不要试图统一所有 Agent 的内部实现,而是提供一个最薄的互操作层。 --- ## 可选扩展 如果需要更丰富的功能,可以逐步添加: - **认证**:在 metadata 中加 `auth_token` - **流式传输**:使用 Server-Sent Events 或 WebSocket - **异步回调**:加 `callback_url` 字段 - **能力协商**:通过 `/mamp/v1/card` 端点 - **错误处理**:标准化错误码 --- ## 实现路线图 ### Phase 1:基础协议(1-2 周) **目标**:实现最简 MAMP 协议 **任务**: 1. 实现 `/mamp/v1/messages` 端点(接收消息) 2. 实现 `/mamp/v1/card` 端点(Agent 身份) 3. 实现 `send_to_agent` 工具(发送消息) 4. 实现 `ConversationStore`(映射管理) 5. 支持纯文本消息 ### Phase 2:多模态支持(1 周) **目标**:支持图片、代码等多模态内容 **任务**: 1. 扩展 content 格式处理 2. 集成现有多模态实现(`agent/llm/prompts/wrapper.py`) 3. 支持 base64 和 URL 两种图片传输方式 ### Phase 3:增强功能(可选) **目标**:认证、流式、异步等高级功能 **任务**: 1. API Key 认证 2. WebSocket 流式传输 3. 异步回调机制 4. 错误处理和重试 --- ## 相关文档 - [A2A 跨设备通信](./a2a-cross-device.md):内部 Agent 间通信方案 - [多模态支持](../../agent/docs/multimodal.md):图片、PDF 处理 - [工具系统](../../agent/docs/tools.md):工具定义、注册 - [Agent 框架](../README.md):核心 Agent 能力