From 7b105ded96b9ec0fcb1da8a7154b66575fd4cb0c Mon Sep 17 00:00:00 2001 From: lychang <632945494@qq.com> Date: Sat, 27 Jun 2026 22:16:05 +0800 Subject: [PATCH] =?UTF-8?q?=E7=81=B5=E9=9A=99(synapse)=20v1.0.0=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/01-synapse-raw-protocol.md | 328 ---------- docs/02-a2a-protocol.md | 465 -------------- docs/02-p2p-protocol.md | 465 -------------- docs/03-a2n-protocol.md | 545 ----------------- docs/03-group-protocol.md | 545 ----------------- docs/04-caller-protocol.md | 503 --------------- docs/04-p2a-protocol.md | 503 --------------- docs/05-sdk-implementation.md | 519 ---------------- docs/06-solutions-whitepaper.md | 777 ------------------------ examples/group_demo.go | 414 ------------- examples/p2p_demo.go | 368 ----------- externalapi/handler.go | 88 +++ sdk/caller/client.go | 547 ----------------- sdk/doc.go | 6 +- sdk/group/client.go | 346 ----------- sdk/p2p/client.go | 459 -------------- synapse/docs/01-synapse-raw-protocol.md | 328 ---------- synapse/docs/02-a2a-protocol.md | 465 -------------- synapse/docs/03-a2n-protocol.md | 545 ----------------- synapse/docs/04-p2a-protocol.md | 503 --------------- synapse/docs/05-sdk-implementation.md | 519 ---------------- synapse/docs/06-solutions-whitepaper.md | 777 ------------------------ types/types.go | 18 +- 23 files changed, 107 insertions(+), 9926 deletions(-) delete mode 100644 docs/01-synapse-raw-protocol.md delete mode 100644 docs/02-a2a-protocol.md delete mode 100644 docs/02-p2p-protocol.md delete mode 100644 docs/03-a2n-protocol.md delete mode 100644 docs/03-group-protocol.md delete mode 100644 docs/04-caller-protocol.md delete mode 100644 docs/04-p2a-protocol.md delete mode 100644 docs/05-sdk-implementation.md delete mode 100644 docs/06-solutions-whitepaper.md delete mode 100644 examples/group_demo.go delete mode 100644 examples/p2p_demo.go delete mode 100644 sdk/caller/client.go delete mode 100644 sdk/group/client.go delete mode 100644 sdk/p2p/client.go delete mode 100644 synapse/docs/01-synapse-raw-protocol.md delete mode 100644 synapse/docs/02-a2a-protocol.md delete mode 100644 synapse/docs/03-a2n-protocol.md delete mode 100644 synapse/docs/04-p2a-protocol.md delete mode 100644 synapse/docs/05-sdk-implementation.md delete mode 100644 synapse/docs/06-solutions-whitepaper.md diff --git a/docs/01-synapse-raw-protocol.md b/docs/01-synapse-raw-protocol.md deleted file mode 100644 index baff41d..0000000 --- a/docs/01-synapse-raw-protocol.md +++ /dev/null @@ -1,328 +0,0 @@ -# 灵隙原始协议(Synapse Raw Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:纲领性文档 - ---- - -## 1. 协议愿景 - -灵隙(Synapse,原 Agent-to-Agent)协议旨在定义一套通用的、可扩展的智能体间通信标准,使不同系统、不同厂商、不同能力的智能体能够在统一的协议框架下进行协作、交易与能力组合。 - -本协议是灵隙协议族(Synapse Protocol Suite)的原始纲领,定义核心设计理念、架构原则与术语体系,为所有衍生协议提供顶层指导。 - ---- - -## 2. 核心设计理念 - -### 2.1 去中心化对等(Peer-to-Peer) -- 所有 Agent 在协议层面地位平等,无中心化控制节点 -- 每个 Agent 既是服务提供者,也是服务消费者 -- Agent 间直接通信,不依赖中间 broker(传输层可选择不同实现) - -### 2.2 能力驱动(Capability-Driven) -- 通信以能力为核心,而非以身份为核心 -- Agent 声明自身能力,按需发现与调用 -- 能力可组合、可分解、可升级 - -### 2.3 任务导向(Task-Oriented) -- 所有交互围绕"任务"展开 -- 任务有明确的生命周期、状态机与超时机制 -- 任务支持拆分、合并、委派与协作 - -### 2.4 人类可介入(Human-in-the-Loop) -- 协议原生支持人类介入决策 -- Agent 可主动请求人类判断 -- 人类决策优先于 Agent 自动决策 -- 支持多级升级(escalation)机制 - -### 2.5 群组协作(Group Collaboration) -- 支持多 Agent 组成临时或永久群组 -- 群组内有角色分工与权限控制 -- 支持任务拆分-执行-合并的 MapReduce 模式 -- 支持投票、共识等群体决策机制 - -### 2.6 传输无关(Transport Agnostic) -- 协议语义与底层传输分离 -- 支持 HTTP/2、gRPC、WebSocket、消息队列等多种传输 -- 支持回调(Callback)、轮询(Polling)、同步(Sync)、混合(Hybrid)等多种交互模式 - -### 2.7 安全可信(Secure & Trustworthy) -- 消息级签名与验证 -- Agent 身份认证与信任等级 -- 支持加密传输 -- 可审计、可追溯 - ---- - -## 3. 协议分层架构 - -``` -┌─────────────────────────────────────────┐ -│ 应用层 (Application) │ -│ 业务逻辑、工作流、领域特定逻辑 │ -├─────────────────────────────────────────┤ -│ 协议层 (Protocol) │ -├─────────────┬───────────────────────────┤ -│ A2A 协议 │ A2N 组群协议 │ ← 本协议族 -│ (P2P) │ (Group) │ -├─────────────┴───────────────────────────┤ -│ 传输层 (Transport) │ -│ HTTP / gRPC / WebSocket / MQ ... │ -├─────────────────────────────────────────┤ -│ 网络层 (Network) │ -│ TCP / UDP / QUIC ... │ -└─────────────────────────────────────────┘ -``` - -### 3.1 协议族构成 - -| 协议名称 | 缩写 | 描述 | 适用场景 | -|---------|------|------|---------| -| 灵隙原始协议(Synapse Raw Protocol) | A2A-Raw | 顶层纲领,定义理念、术语、原则 | 指导所有协议设计 | -| A2A 协议 | A2A-Base | 点对点任务协作协议 | 两个 Agent 间的任务交互 | -| A2N 组群协议 | A2N-Group | 多 Agent 群组协作协议 | 多个 Agent 协同完成任务 | -| P2A 调用协议 | P2A-Caller | 非 Agent 调用者接入协议 | 普通服务/前端调用 Agent 能力 | - ---- - -## 4. 核心概念与术语 - -### 4.1 Agent(智能体) -能够自主感知环境、做出决策并执行动作的计算实体。 - -**属性:** -- `agent_id`:Agent 唯一标识 -- `system_id`:所属系统标识 -- `endpoint`:通信端点地址 -- `capabilities`:能力清单 -- `trust_level`:信任等级 - -### 4.2 Task(任务) -Agent 间协作的基本单位,具有明确的输入、输出与生命周期。 - -**属性:** -- `task_id`:任务唯一标识 -- `task_type`:任务类型 -- `payload`:任务载荷 -- `status`:任务状态 -- `priority`:优先级 -- `deadline`:截止时间 - -### 4.3 Message(消息) -Agent 间通信的基本单位。 - -**属性:** -- `message_id`:消息唯一标识 -- `type`:消息类型 -- `sender`:发送方 -- `receiver`:接收方(P2P) -- `group_id`:群组标识(群组) -- `payload`:消息载荷 -- `correlation_id`:关联标识(用于请求-响应关联) -- `timestamp`:时间戳 -- `signature`:签名 - -### 4.4 Capability(能力) -Agent 能够执行的任务类型的声明。 - -**属性:** -- `type`:能力对应的任务类型 -- `name`:能力名称 -- `description`:能力描述 -- `input_schema`:输入参数 schema -- `output_schema`:输出结果 schema -- `estimated_time`:预估耗时 - -### 4.5 Group(群组) -由多个 Agent 组成的协作单元。 - -**属性:** -- `group_id`:群组唯一标识 -- `name`:群组名称 -- `topology`:拓扑结构 -- `members`:成员列表 -- `roles`:角色定义 -- `status`:群组状态 - -### 4.6 Human-in-the-Loop(人在回路) -在 Agent 协作过程中,人类可介入进行决策的机制。 - -**关键概念:** -- `escalation`:升级(将问题提交给人类) -- `decision`:决策(人类做出的判断) -- `resume`:恢复(人类决策后继续执行) - ---- - -## 5. 设计原则 - -### 5.1 简约性(Simplicity) -- 核心机制保持简单 -- 复杂功能通过组合基础机制实现 -- 可选功能通过能力声明来协商 - -### 5.2 可扩展性(Extensibility) -- 消息类型可扩展 -- 能力类型可扩展 -- 传输方式可扩展 -- 通过版本号与能力协商保证向后兼容 - -### 5.3 容错性(Fault Tolerance) -- 网络不可靠是常态 -- 消息可能丢失、重复、延迟 -- Agent 可能故障、离线 -- 协议必须有重试、超时、降级机制 - -### 5.4 可观测性(Observability) -- 所有交互可追踪 -- 任务状态可查询 -- 支持日志、指标、链路追踪 - -### 5.5 互操作性(Interoperability) -- 不同语言、不同框架的 Agent 可互操作 -- 协议规范优先于具体实现 -- 提供标准测试用例验证兼容性 - ---- - -## 6. 消息模型总则 - -### 6.1 统一消息信封 -所有协议共享统一的消息信封结构,具体载荷由消息类型决定。 - -``` -UnifiedSynapseMessage -├── id // 消息ID -├── version // 协议版本 -├── type // 消息类型 -├── sender // 发送方 AgentEndpoint -├── receiver? // 接收方(P2P 时) -├── group_id? // 群组ID(群组时) -├── correlation_id // 关联ID -├── reply_to? // 回复的消息ID -├── payload // 消息载荷(JSON) -├── priority? // 优先级 -├── signature? // 签名 -├── timestamp // 发送时间 -└── expires_at? // 过期时间 -``` - -### 6.2 消息命名规范 -- 使用 `领域:动作` 格式 -- 全小写,用下划线分隔 -- 示例:`p2p:task_request`, `group:create`, `hil:decision` - -### 6.3 请求-响应模式 -- 请求消息必须携带唯一 `id` -- 响应消息通过 `reply_to` 关联请求 -- 支持 ACK/NACK 机制 -- 超时未收到响应应重试或报错 - ---- - -## 7. 任务生命周期总则 - -### 7.1 状态机 - -``` - ┌──────────┐ - │ pending │ 待确认 - └────┬─────┘ - │ 确认/拒绝 - ┌─────┴──────┐ - ▼ ▼ - ┌─────────┐ ┌──────────┐ - │confirmed│ │ rejected │ 已拒绝(终态) - └────┬────┘ └──────────┘ - │ 开始执行 - ▼ - ┌──────────┐ - │executing │ 执行中 - └────┬─────┘ - │ 信息缺失 - ┌────▼─────┐ - │info_needed│ 需要信息 - └────┬─────┘ - │ 信息补充 - ▼ - 回到 executing - │ - ├──────────────┐ - │ 需人类决策 │ - ▼ ▼ - ┌──────────┐ ┌───────────┐ - │need_human│ │ 各种终态 │ - └────┬─────┘ └───────────┘ - │ 人类决策 - ▼ - 回到 executing - │ - ┌────┴────┬─────────┐ - ▼ ▼ ▼ -completed failed cancelled -(完成) (失败) (取消) -``` - -### 7.2 终态 -- `completed`:成功完成 -- `failed`:执行失败 -- `cancelled`:被取消 -- `rejected`:被拒绝 - ---- - -## 8. 安全模型总则 - -### 8.1 身份认证 -- 每个 Agent 有唯一身份 -- 支持 HMAC、JWT、OAuth2 等多种认证方式 -- 信任等级机制 - -### 8.2 消息完整性 -- 消息签名机制 -- 防止篡改与伪造 - -### 8.3 机密性 -- 支持端到端加密 -- 敏感载荷加密传输 - -### 8.4 访问控制 -- 基于信任等级的权限控制 -- 群组内基于角色的权限控制 - ---- - -## 9. 非目标 - -以下内容**不在**本原始协议的讨论范围内: - -1. **具体传输协议的实现细节** - 由各传输层实现定义 -2. **特定领域的任务类型** - 由应用层或领域扩展定义 -3. **Agent 内部实现架构** - 仅定义对外接口与行为 -4. **具体编程语言绑定** - 语言无关,可多语言实现 -5. **UI/UX 设计** - 人机界面不在协议范围内 - ---- - -## 10. 参考实现 - -本协议族的参考实现位于:`dp-headless/synapse/` - -| 模块 | 对应协议 | 文件路径 | -|------|---------|---------| -| types 包 | 公共类型定义 | `types/` | -| p2p 包 | A2A 协议 | `p2p/` | -| group 包 | A2N 组群协议 | `group/` | -| externalapi 包 | P2A 调用协议 | `externalapi/` | -| sdk 包 | P2A 客户端 SDK | `sdk/` | - ---- - -## 附录 A:协议演进 - -本原始协议作为顶层指导,保持相对稳定。各具体协议可独立版本化演进,但需遵循本协议定义的核心原则。 - -**版本历史:** -- v1.0.0:初始版本,定义核心概念与设计原则 diff --git a/docs/02-a2a-protocol.md b/docs/02-a2a-protocol.md deleted file mode 100644 index 8a5da2a..0000000 --- a/docs/02-a2a-protocol.md +++ /dev/null @@ -1,465 +0,0 @@ -# A2A 协议(Agent-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -A2A 协议定义了两个 Agent 之间进行点对点(P2P)任务协作的完整规范,包括消息类型、交互流程、状态机、接口定义与错误处理。 - -### 1.1 适用场景 -- 单个任务请求与响应 -- 任务状态实时同步 -- 任务取消 -- 信息补全交互 -- 人类介入决策 - -### 1.2 非适用场景 -- 多 Agent 群组协作(参见 A2N 组群协议) -- 非 Agent 调用方接入(参见 P2A 调用协议) - ---- - -## 2. 消息类型 - -### 2.1 消息类型清单 - -所有消息类型前缀:`p2p:` - -| 消息类型 | 方向 | 说明 | -|---------|------|------| -| `p2p:task_request` | 请求方 → 执行方 | 提交任务请求 | -| `p2p:task_confirm` | 执行方 → 请求方 | 确认接受任务 | -| `p2p:task_reject` | 执行方 → 请求方 | 拒绝任务 | -| `p2p:task_need_info` | 执行方 → 请求方 | 请求补充信息 | -| `p2p:task_info_provided` | 请求方 → 执行方 | 提供补充信息 | -| `p2p:task_status_update` | 执行方 → 请求方 | 任务进度更新 | -| `p2p:task_complete` | 执行方 → 请求方 | 任务完成 | -| `p2p:task_failed` | 执行方 → 请求方 | 任务失败 | -| `p2p:task_cancel` | 请求方 → 执行方 | 取消任务 | -| `p2p:task_ack` | 双向 | 任务级确认 | -| `p2p:ack` | 双向 | 通用确认 | -| `p2p:nack` | 双向 | 通用否定确认(错误) | -| `p2p:heartbeat` | 双向 | 心跳保活 | -| `p2p:capability_query` | 双向 | 查询对方能力 | -| `p2p:capability_response` | 双向 | 返回能力清单 | -| `p2p:task_need_human` | 执行方 → 请求方 | 请求人类介入 | -| `p2p:human_decision` | 请求方 → 执行方 | 人类决策结果 | - -### 2.2 消息类型完整定义 - -参见代码:[types/types.go](../types/types.go) - ---- - -## 3. 任务状态机 - -### 3.1 状态定义 - -| 状态 | 说明 | -|------|------| -| `idle` | 空闲(初始状态) | -| `pending` | 待确认(已发送请求,等待确认) | -| `confirmed` | 已确认(对方接受任务) | -| `executing` | 执行中 | -| `info_needed` | 需要信息 | -| `info_provided` | 信息已提供 | -| `need_human` | 需要人类介入 | -| `human_deciding` | 人类决策中 | -| `human_approved` | 人类已批准 | -| `human_rejected` | 人类已拒绝 | -| `completed` | 已完成(终态) | -| `failed` | 已失败(终态) | -| `cancelled` | 已取消(终态) | -| `rejected` | 已拒绝(终态) | - -### 3.2 状态流转图 - -``` -请求方视角: - -idle → pending → confirmed → executing → completed - ↓ ↓ → failed - rejected info_needed → cancelled - ↑↓ - info_provided - ↓ - need_human - ↑↓ - human_decision -``` - ---- - -## 4. 核心交互流程 - -### 4.1 正常任务提交流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| 1. 提交任务 - | | - |<------- task_confirm / task_reject -| 2. 确认/拒绝 - | | - |<------- task_status_update --------| 3. 进度更新(多次) - | | - |<------- task_complete -------------| 4. 完成通知 - | | - |-------- task_ack ----------------->| 5. 确认收到 - | | -``` - -### 4.2 信息补全流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_info ------------| 发现信息缺失 - | | - |-------- task_info_provided ------->| 补充信息 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.3 人类介入流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_human -----------| 需要人类决策 - | | - | [人类做出决策] | - | | - |-------- human_decision ----------->| 决策结果 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.4 任务取消流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |-------- task_cancel -------------->| 取消任务 - | | - |<------- task_ack ------------------| 确认取消 - | | -``` - ---- - -## 5. 接口规范 - -### 5.1 P2P 协议处理器接口 - -**接口定义:** - -```go -type P2PProtocol interface { - // 处理收到的消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h TaskHandler) - - // 设置回调发送器 - SetCallbackSender(s CallbackSender) - - // 获取 Agent 端点 - AgentEndpoint() AgentEndpoint - - // 查询任务状态 - GetTaskStatus(taskID string) (P2PTaskStatus, bool) - - // 列出所有任务 - ListTasks() map[string]P2PTaskStatus -} -``` - -**参考实现:** [p2p/protocol.go](../p2p/protocol.go) - -### 5.2 任务处理器接口 - -```go -type TaskHandler interface { - // 执行任务并返回结果 - ExecuteTask(ctx context.Context, taskType string, payload map[string]interface{}) (any, error) - - // 验证任务是否可执行,返回缺失字段列表和是否可处理 - ValidateTask(taskType string, payload map[string]interface{}) ([]MissingField, bool) - - // 获取能力列表 - GetCapabilities() []string -} -``` - -**说明:** -- `ExecuteTask`:实际执行业务逻辑的入口 -- `ValidateTask`:在任务确认前调用,用于判断是否接受任务或需要补充信息 -- `GetCapabilities`:返回 Agent 支持的任务类型列表 - -### 5.3 回调发送器接口 - -```go -type CallbackSender interface { - // 向远程 Agent 发送消息 - SendCallback(ctx context.Context, endpoint string, msg *UnifiedSynapseMessage) error -} -``` - -**说明:** -- 传输层实现此接口 -- 支持多种传输方式(HTTP、gRPC、WebSocket 等) - -### 5.4 配置项 - -```go -type P2PConfig struct { - MaxRetries int // 最大重试次数(默认 5) - RetryBaseDelay time.Duration // 重试基础延迟(默认 2s,指数退避) - TaskTimeout time.Duration // 任务执行超时(默认 5 分钟) - HeartbeatInterval time.Duration // 心跳间隔(默认 30 秒) -} -``` - ---- - -## 6. 载荷格式 - -### 6.1 TaskRequestPayload(任务请求) - -```json -{ - "task": { - "id": "task-xxx", - "type": "text_generation", - "priority": "normal", - "deadline": "2026-01-01T00:00:00Z", - "payload": { - "prompt": "写一首诗", - "style": "古典" - } - }, - "context": { - "session_id": "sess-xxx", - "parent_task_id": "parent-xxx", - "correlation_id": "corr-xxx", - "metadata": {} - } -} -``` - -### 6.2 TaskConfirmPayload(任务确认) - -```json -{ - "task_id": "task-xxx", - "confirmed": true, - "estimated_duration": 120, - "expected_completion": "2026-01-01T00:02:00Z", - "capabilities_used": ["text_generation"], - "constraints": { - "max_retries": 3, - "fallback_enabled": true - } -} -``` - -### 6.3 TaskRejectPayload(任务拒绝) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "capability_lacking", - "message": "不支持该任务类型", - "details": null - }, - "alternatives": { - "suggested_agent_id": "other-agent", - "retry_after": 300, - "partial_support": false - } -} -``` - -### 6.4 TaskStatusUpdatePayload(状态更新) - -```json -{ - "task_id": "task-xxx", - "status": "executing", - "progress": 50, - "message": "正在生成内容", - "intermediate_result": null -} -``` - -### 6.5 TaskCompletePayload(任务完成) - -```json -{ - "task_id": "task-xxx", - "result": { - "output_type": "text", - "output": "生成的文本内容...", - "metadata": { - "tokens": 1024, - "model": "gpt-4" - } - }, - "summary": "任务已完成" -} -``` - -### 6.6 TaskFailedPayload(任务失败) - -```json -{ - "task_id": "task-xxx", - "error": { - "code": "execution_error", - "message": "模型调用超时", - "recoverable": true, - "details": null - }, - "partial_result": null -} -``` - -### 6.7 TaskNeedInfoPayload(需要信息) - -```json -{ - "task_id": "task-xxx", - "missing_fields": [ - { - "field": "style", - "reason": "未指定生成风格", - "suggested_value": "古典", - "alternatives": ["现代", "浪漫"] - } - ], - "question": "请选择生成风格", - "required_by": "2026-01-01T00:01:00Z" -} -``` - -### 6.8 TaskNeedHumanPayload(需要人类) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "ethical_decision", - "message": "涉及伦理决策需要人工审核" - }, - "context": { - "task_summary": "生成一张人物肖像", - "current_progress": 30, - "blocked_reason": "需要确认肖像使用授权" - }, - "options": [ - { - "field": "authorized", - "value": true, - "pros_cons": "继续生成,假设已授权", - "confidence": 70 - } - ], - "escalation_level": 1, - "deadline": "2026-01-01T00:05:00Z" -} -``` - -### 6.9 HumanDecisionPayload(人类决策) - -```json -{ - "task_id": "task-xxx", - "decision_id": "dec-xxx", - "reply_to": "msg-xxx", - "decided_by": { - "user_id": "user-123", - "user_name": "张三", - "role": "reviewer" - }, - "decision": { - "action": "approve", - "approved_fields": { - "authorized": true - }, - "rejection_reason": "" - }, - "notes": "已确认授权", - "timestamp": "2026-01-01T00:03:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 7. 错误码 - -| 错误码 | 说明 | HTTP 状态码(如适用) | -|--------|------|---------------------| -| `message_format_invalid` | 消息格式无效 | 400 | -| `capability_lacking` | 能力不足 | 403 | -| `agent_not_ready` | Agent 未就绪 | 503 | -| `task_not_found` | 任务不存在 | 404 | -| `task_already_completed` | 任务已完成 | 409 | -| `execution_timeout` | 执行超时 | 504 | -| `execution_failed` | 执行失败 | 500 | -| `permission_denied` | 权限不足 | 403 | -| `invalid_params` | 参数无效 | 400 | -| `rate_limited` | 限流 | 429 | - -**完整错误定义:** [types/errors.go](../types/errors.go) - ---- - -## 8. 传输要求 - -### 8.1 HTTP 传输 -- Content-Type: `application/json` -- 请求方法:`POST` -- 端点路径:由 Agent 自行定义,建议 `/synapse/callback` -- 超时:建议 30 秒 - -### 8.2 签名验证(可选) -- 使用 HMAC-SHA256 签名 -- 签名放在 Header:`X-Synapse-Signature` -- 或放在消息体:`signature` 字段 - ---- - -## 9. 参考实现 - -本协议的参考实现位于 `p2p/` 目录: - -| 文件 | 说明 | -|------|------| -| [p2p/protocol.go](../p2p/protocol.go) | P2P 协议核心实现 | -| [types/types.go](../types/types.go) | 数据类型定义 | -| [types/errors.go](../types/errors.go) | 错误定义 | -| [transport/transport.go](../transport/transport.go) | HTTP 传输实现 | - ---- - -## 附录 A:能力声明格式 - -参见 [灵隙原始协议(Synapse Raw Protocol) - Capability](./01-synapse-raw-protocol.md#44-capability能力) diff --git a/docs/02-p2p-protocol.md b/docs/02-p2p-protocol.md deleted file mode 100644 index 9c969f8..0000000 --- a/docs/02-p2p-protocol.md +++ /dev/null @@ -1,465 +0,0 @@ -# A2A 协议(Agent-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-a2a-raw-protocol.md) - ---- - -## 1. 概述 - -A2A 协议定义了两个 Agent 之间进行点对点(P2P)任务协作的完整规范,包括消息类型、交互流程、状态机、接口定义与错误处理。 - -### 1.1 适用场景 -- 单个任务请求与响应 -- 任务状态实时同步 -- 任务取消 -- 信息补全交互 -- 人类介入决策 - -### 1.2 非适用场景 -- 多 Agent 群组协作(参见 A2N 组群协议) -- 非 Agent 调用方接入(参见 P2A 调用协议) - ---- - -## 2. 消息类型 - -### 2.1 消息类型清单 - -所有消息类型前缀:`p2p:` - -| 消息类型 | 方向 | 说明 | -|---------|------|------| -| `p2p:task_request` | 请求方 → 执行方 | 提交任务请求 | -| `p2p:task_confirm` | 执行方 → 请求方 | 确认接受任务 | -| `p2p:task_reject` | 执行方 → 请求方 | 拒绝任务 | -| `p2p:task_need_info` | 执行方 → 请求方 | 请求补充信息 | -| `p2p:task_info_provided` | 请求方 → 执行方 | 提供补充信息 | -| `p2p:task_status_update` | 执行方 → 请求方 | 任务进度更新 | -| `p2p:task_complete` | 执行方 → 请求方 | 任务完成 | -| `p2p:task_failed` | 执行方 → 请求方 | 任务失败 | -| `p2p:task_cancel` | 请求方 → 执行方 | 取消任务 | -| `p2p:task_ack` | 双向 | 任务级确认 | -| `p2p:ack` | 双向 | 通用确认 | -| `p2p:nack` | 双向 | 通用否定确认(错误) | -| `p2p:heartbeat` | 双向 | 心跳保活 | -| `p2p:capability_query` | 双向 | 查询对方能力 | -| `p2p:capability_response` | 双向 | 返回能力清单 | -| `p2p:task_need_human` | 执行方 → 请求方 | 请求人类介入 | -| `p2p:human_decision` | 请求方 → 执行方 | 人类决策结果 | - -### 2.2 消息类型完整定义 - -参见代码:[types/types.go](../types/types.go) - ---- - -## 3. 任务状态机 - -### 3.1 状态定义 - -| 状态 | 说明 | -|------|------| -| `idle` | 空闲(初始状态) | -| `pending` | 待确认(已发送请求,等待确认) | -| `confirmed` | 已确认(对方接受任务) | -| `executing` | 执行中 | -| `info_needed` | 需要信息 | -| `info_provided` | 信息已提供 | -| `need_human` | 需要人类介入 | -| `human_deciding` | 人类决策中 | -| `human_approved` | 人类已批准 | -| `human_rejected` | 人类已拒绝 | -| `completed` | 已完成(终态) | -| `failed` | 已失败(终态) | -| `cancelled` | 已取消(终态) | -| `rejected` | 已拒绝(终态) | - -### 3.2 状态流转图 - -``` -请求方视角: - -idle → pending → confirmed → executing → completed - ↓ ↓ → failed - rejected info_needed → cancelled - ↑↓ - info_provided - ↓ - need_human - ↑↓ - human_decision -``` - ---- - -## 4. 核心交互流程 - -### 4.1 正常任务提交流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| 1. 提交任务 - | | - |<------- task_confirm / task_reject -| 2. 确认/拒绝 - | | - |<------- task_status_update --------| 3. 进度更新(多次) - | | - |<------- task_complete -------------| 4. 完成通知 - | | - |-------- task_ack ----------------->| 5. 确认收到 - | | -``` - -### 4.2 信息补全流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_info ------------| 发现信息缺失 - | | - |-------- task_info_provided ------->| 补充信息 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.3 人类介入流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_human -----------| 需要人类决策 - | | - | [人类做出决策] | - | | - |-------- human_decision ----------->| 决策结果 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.4 任务取消流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |-------- task_cancel -------------->| 取消任务 - | | - |<------- task_ack ------------------| 确认取消 - | | -``` - ---- - -## 5. 接口规范 - -### 5.1 P2P 协议处理器接口 - -**接口定义:** - -```go -type P2PProtocol interface { - // 处理收到的消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h TaskHandler) - - // 设置回调发送器 - SetCallbackSender(s CallbackSender) - - // 获取 Agent 端点 - AgentEndpoint() AgentEndpoint - - // 查询任务状态 - GetTaskStatus(taskID string) (P2PTaskStatus, bool) - - // 列出所有任务 - ListTasks() map[string]P2PTaskStatus -} -``` - -**参考实现:** [p2p/protocol.go](../p2p/protocol.go) - -### 5.2 任务处理器接口 - -```go -type TaskHandler interface { - // 执行任务并返回结果 - ExecuteTask(ctx context.Context, taskType string, payload map[string]interface{}) (any, error) - - // 验证任务是否可执行,返回缺失字段列表和是否可处理 - ValidateTask(taskType string, payload map[string]interface{}) ([]MissingField, bool) - - // 获取能力列表 - GetCapabilities() []string -} -``` - -**说明:** -- `ExecuteTask`:实际执行业务逻辑的入口 -- `ValidateTask`:在任务确认前调用,用于判断是否接受任务或需要补充信息 -- `GetCapabilities`:返回 Agent 支持的任务类型列表 - -### 5.3 回调发送器接口 - -```go -type CallbackSender interface { - // 向远程 Agent 发送消息 - SendCallback(ctx context.Context, endpoint string, msg *UnifiedSynapseMessage) error -} -``` - -**说明:** -- 传输层实现此接口 -- 支持多种传输方式(HTTP、gRPC、WebSocket 等) - -### 5.4 配置项 - -```go -type P2PConfig struct { - MaxRetries int // 最大重试次数(默认 5) - RetryBaseDelay time.Duration // 重试基础延迟(默认 2s,指数退避) - TaskTimeout time.Duration // 任务执行超时(默认 5 分钟) - HeartbeatInterval time.Duration // 心跳间隔(默认 30 秒) -} -``` - ---- - -## 6. 载荷格式 - -### 6.1 TaskRequestPayload(任务请求) - -```json -{ - "task": { - "id": "task-xxx", - "type": "text_generation", - "priority": "normal", - "deadline": "2026-01-01T00:00:00Z", - "payload": { - "prompt": "写一首诗", - "style": "古典" - } - }, - "context": { - "session_id": "sess-xxx", - "parent_task_id": "parent-xxx", - "correlation_id": "corr-xxx", - "metadata": {} - } -} -``` - -### 6.2 TaskConfirmPayload(任务确认) - -```json -{ - "task_id": "task-xxx", - "confirmed": true, - "estimated_duration": 120, - "expected_completion": "2026-01-01T00:02:00Z", - "capabilities_used": ["text_generation"], - "constraints": { - "max_retries": 3, - "fallback_enabled": true - } -} -``` - -### 6.3 TaskRejectPayload(任务拒绝) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "capability_lacking", - "message": "不支持该任务类型", - "details": null - }, - "alternatives": { - "suggested_agent_id": "other-agent", - "retry_after": 300, - "partial_support": false - } -} -``` - -### 6.4 TaskStatusUpdatePayload(状态更新) - -```json -{ - "task_id": "task-xxx", - "status": "executing", - "progress": 50, - "message": "正在生成内容", - "intermediate_result": null -} -``` - -### 6.5 TaskCompletePayload(任务完成) - -```json -{ - "task_id": "task-xxx", - "result": { - "output_type": "text", - "output": "生成的文本内容...", - "metadata": { - "tokens": 1024, - "model": "gpt-4" - } - }, - "summary": "任务已完成" -} -``` - -### 6.6 TaskFailedPayload(任务失败) - -```json -{ - "task_id": "task-xxx", - "error": { - "code": "execution_error", - "message": "模型调用超时", - "recoverable": true, - "details": null - }, - "partial_result": null -} -``` - -### 6.7 TaskNeedInfoPayload(需要信息) - -```json -{ - "task_id": "task-xxx", - "missing_fields": [ - { - "field": "style", - "reason": "未指定生成风格", - "suggested_value": "古典", - "alternatives": ["现代", "浪漫"] - } - ], - "question": "请选择生成风格", - "required_by": "2026-01-01T00:01:00Z" -} -``` - -### 6.8 TaskNeedHumanPayload(需要人类) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "ethical_decision", - "message": "涉及伦理决策需要人工审核" - }, - "context": { - "task_summary": "生成一张人物肖像", - "current_progress": 30, - "blocked_reason": "需要确认肖像使用授权" - }, - "options": [ - { - "field": "authorized", - "value": true, - "pros_cons": "继续生成,假设已授权", - "confidence": 70 - } - ], - "escalation_level": 1, - "deadline": "2026-01-01T00:05:00Z" -} -``` - -### 6.9 HumanDecisionPayload(人类决策) - -```json -{ - "task_id": "task-xxx", - "decision_id": "dec-xxx", - "reply_to": "msg-xxx", - "decided_by": { - "user_id": "user-123", - "user_name": "张三", - "role": "reviewer" - }, - "decision": { - "action": "approve", - "approved_fields": { - "authorized": true - }, - "rejection_reason": "" - }, - "notes": "已确认授权", - "timestamp": "2026-01-01T00:03:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 7. 错误码 - -| 错误码 | 说明 | HTTP 状态码(如适用) | -|--------|------|---------------------| -| `message_format_invalid` | 消息格式无效 | 400 | -| `capability_lacking` | 能力不足 | 403 | -| `agent_not_ready` | Agent 未就绪 | 503 | -| `task_not_found` | 任务不存在 | 404 | -| `task_already_completed` | 任务已完成 | 409 | -| `execution_timeout` | 执行超时 | 504 | -| `execution_failed` | 执行失败 | 500 | -| `permission_denied` | 权限不足 | 403 | -| `invalid_params` | 参数无效 | 400 | -| `rate_limited` | 限流 | 429 | - -**完整错误定义:** [types/errors.go](../types/errors.go) - ---- - -## 8. 传输要求 - -### 8.1 HTTP 传输 -- Content-Type: `application/json` -- 请求方法:`POST` -- 端点路径:由 Agent 自行定义,建议 `/synapse/callback` -- 超时:建议 30 秒 - -### 8.2 签名验证(可选) -- 使用 HMAC-SHA256 签名 -- 签名放在 Header:`X-Synapse-Signature` -- 或放在消息体:`signature` 字段 - ---- - -## 9. 参考实现 - -本协议的参考实现位于 `p2p/` 目录: - -| 文件 | 说明 | -|------|------| -| [p2p/protocol.go](../p2p/protocol.go) | P2P 协议核心实现 | -| [types/types.go](../types/types.go) | 数据类型定义 | -| [types/errors.go](../types/errors.go) | 错误定义 | -| [transport/transport.go](../transport/transport.go) | HTTP 传输实现 | - ---- - -## 附录 A:能力声明格式 - -参见 [灵隙原始协议(Synapse Raw Protocol) - Capability](./01-a2a-raw-protocol.md#44-capability能力) diff --git a/docs/03-a2n-protocol.md b/docs/03-a2n-protocol.md deleted file mode 100644 index fa70c90..0000000 --- a/docs/03-a2n-protocol.md +++ /dev/null @@ -1,545 +0,0 @@ -# A2N 协议(Agent-to-N Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -A2N(Agent-to-N)组群协议定义了多个 Agent 组成群组进行协同工作的完整规范,包括群组管理、任务拆分与合并、群体决策、角色与权限等。 - -### 1.1 适用场景 -- 复杂任务的拆分与并行执行(MapReduce 模式) -- 多 Agent 协同完成单一目标 -- 群体投票与共识决策 -- 临时或永久的 Agent 工作组 -- 分级升级(escalation)机制 - -### 1.2 依赖 -- 依赖 A2A 协议的点对点通信能力 -- 群组内成员间的单播通信使用 A2A 协议 - ---- - -## 2. 核心概念 - -### 2.1 Group(群组) -由多个 Agent 组成的协作单元,具有明确的拓扑结构、角色分工与协作规则。 - -### 2.2 Topology(拓扑结构) - -| 拓扑类型 | 说明 | 适用场景 | -|---------|------|---------| -| `star` | 星型,中心 coordinator 协调 | 简单任务分发 | -| `mesh` | 网状,成员间可直接通信 | 对等协作 | -| `chain` | 链式,流水线模式 | 顺序处理 | -| `hierarchical` | 层级型,多层管理 | 大型复杂任务 | -| `fullmesh` | 全连接网状 | 高可靠协作 | - -### 2.3 Role(角色) - -| 角色 | 说明 | 权限 | -|------|------|------| -| `coordinator` | 协调者 | 创建/解散群组、任务拆分、发起投票 | -| `worker` | 工作者 | 执行子任务、提交结果 | -| `reviewer` | 审核者 | 审核结果、发起投票 | -| `observer` | 观察者 | 只读,查看进度 | - -### 2.4 GroupStatus(群组状态) - -| 状态 | 说明 | -|------|------| -| `creating` | 创建中 | -| `active` | 活跃 | -| `frozen` | 冻结(不可执行新任务) | -| `disbanded` | 已解散(终态) | - ---- - -## 3. 消息类型 - -### 3.1 消息类型清单 - -所有消息类型前缀:`group:` 或 `inter_group:` - -#### 群组管理 - -| 消息类型 | 说明 | -|---------|------| -| `group:create` | 创建群组 | -| `group:disband` | 解散群组 | -| `group:join` | 加入群组 | -| `group:leave` | 离开群组 | -| `group:invite` | 邀请加入 | -| `group:accept_invite` | 接受邀请 | -| `group:reject_invite` | 拒绝邀请 | -| `group:member_update` | 成员更新通知 | -| `group:role_change` | 角色变更 | - -#### 群组通信 - -| 消息类型 | 说明 | -|---------|------| -| `group:broadcast` | 广播(所有成员) | -| `group:multicast` | 组播(指定成员) | -| `group:direct` | 群内单播 | -| `group:relay` | 消息中继 | - -#### 任务协作 - -| 消息类型 | 说明 | -|---------|------| -| `group:task_split` | 任务拆分 | -| `group:task_assign` | 任务分配 | -| `group:task_merge` | 结果合并 | -| `group:task_progress` | 子任务进度 | - -#### 共识与投票 - -| 消息类型 | 说明 | -|---------|------| -| `group:vote` | 发起投票 | -| `group:vote_submit` | 提交投票 | -| `group:consensus` | 达成共识 | - -#### 人在回路(HiL) - -| 消息类型 | 说明 | -|---------|------| -| `group:consensus_escalate` | 共识僵局升级给人类 | -| `group:subtask_escalate` | 子任务阻塞升级给人类 | -| `group:human_decision` | 人类决策结果 | -| `inter_group:escalate` | 跨群组升级 | - -**完整定义:** [types/types.go](../types/types.go) - ---- - -## 4. 群组生命周期 - -### 4.1 状态机 - -``` -creating → active → frozen → disbanded - ↑ ↓ - └─────────┘ - 解冻 -``` - -### 4.2 群组创建流程 - -``` -创建者 被邀请成员 - | | - |------ group:invite -------------->| 发送邀请 - | | - |<----- group:accept_invite --------| 接受邀请 - | | - |------ group:member_update ------->| 通知成员更新 - | | - [群组创建完成,状态变为 active] | -``` - -### 4.3 群组解散流程 - -``` -coordinator 所有成员 - | | - |------ group:disband ------------->| 通知解散 - | | - [群组状态变为 disbanded] | -``` - ---- - -## 5. 任务协作流程 - -### 5.1 MapReduce 模式(拆分-执行-合并) - -``` - ┌──────────────┐ - │ coordinator │ - └──────┬───────┘ - │ - group:task_split(拆分任务) - │ - ┌────────────────┼────────────────┐ - ▼ ▼ ▼ - ┌─────────┐ ┌─────────┐ ┌─────────┐ - │ worker1 │ │ worker2 │ │ worker3 │ - └────┬────┘ └────┬────┘ └────┬────┘ - │ │ │ - │ 执行子任务 │ 执行子任务 │ 执行子任务 - │ │ │ - ▼ ▼ ▼ - 子任务结果 子任务结果 子任务结果 - └────────────────┼────────────────┘ - │ - group:task_merge(合并结果) - ▼ - ┌──────────────┐ - │ 最终结果 │ - └──────────────┘ -``` - -### 5.2 详细流程 - -1. **任务拆分阶段** - - coordinator 接收原始任务 - - 将任务拆分为多个子任务(subtask) - - 为每个子任务指定执行的 worker - - 定义合并策略(merge strategy) - -2. **并行执行阶段** - - 各 worker 并行执行子任务 - - 定期上报进度(`group:task_progress`) - - 子任务完成后上报结果 - -3. **结果合并阶段** - - 所有子任务完成后,coordinator 合并结果 - - 根据合并策略决定最终结果 - - 输出最终结果 - ---- - -## 6. 合并策略(Merge Strategy) - -| 策略 | 说明 | -|------|------| -| `all_success` | 全部成功才认为成功,否则失败 | -| `majority` | 多数子任务成功即可,取多数结果 | -| `any_complete` | 任意一个完成即返回结果 | -| `priority` | 按优先级,高优先级子任务结果优先 | - ---- - -## 7. 投票与共识 - -### 7.1 投票流程 - -``` -发起者 投票者 - | | - |-------- group:vote -------------->| 发起投票 - | | - |<------- group:vote_submit --------| 提交投票 - | | - [计票,判断是否达到阈值] | - | | - |-------- group:consensus --------->| 公布结果 - | | -``` - -### 7.2 投票规则 - -- `threshold`:通过阈值(0-1),如 0.5 表示过半 -- `deadline`:投票截止时间 -- `voters`:有投票权的成员列表 -- 超时未投票视为弃权 - -### 7.3 共识僵局(Consensus Deadlock) - -当投票无法达成共识(如平票、未达阈值且超时)时,可升级给人类决策。 - ---- - -## 8. 人在回路(HiL) - -群组协作中有两种升级场景: - -### 8.1 共识僵局升级 -投票无法达成共识时,升级给人类裁决。 - -**消息:** `group:consensus_escalate` - -### 8.2 子任务阻塞升级 -某个子任务遇到无法自动解决的问题时,升级给人类。 - -**消息:** `group:subtask_escalate` - -### 8.3 跨群组升级 -问题超出当前群组能力时,可升级到上级群组或人类。 - -**消息:** `inter_group:escalate` - ---- - -## 9. 接口规范 - -### 9.1 GroupProtocol 接口 - -```go -type GroupProtocol interface { - // 处理群组消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h GroupTaskHandler) - - // 查询群组列表 - GetGroups() []*AgentGroup - - // 查询特定群组 - GetGroup(groupID string) (*AgentGroup, bool) -} -``` - -**参考实现:** [group/protocol.go](../group/protocol.go) - -### 9.2 GroupTaskHandler 接口 - -```go -type GroupTaskHandler interface { - // 执行子任务 - ExecuteSubtask(ctx context.Context, subtaskID string, payload map[string]interface{}) (any, error) - - // 合并多个子任务结果 - MergeResults(results []SubtaskResult, strategy MergeStrategy) (any, error) - - // 验证任务是否可拆分,返回拆分方案 - ValidateTaskSplit(taskType string, requirements map[string]interface{}) ([]Subtask, bool) -} -``` - -**说明:** -- `ExecuteSubtask`:执行单个子任务的业务逻辑 -- `MergeResults`:根据策略合并多个子任务的结果 -- `ValidateTaskSplit`:验证任务是否可拆分,并给出拆分方案 - -### 9.3 配置项 - -```go -type GroupConfig struct { - MaxGroupSize int // 最大群组人数(默认 20) - MaxSubtasks int // 最大子任务数(默认 50) - ConsensusTimeout time.Duration // 共识超时(默认 5 分钟) - TaskTimeout time.Duration // 任务超时(默认 10 分钟) -} -``` - ---- - -## 10. 载荷格式 - -### 10.1 GroupCreatePayload(创建群组) - -```json -{ - "group": { - "name": "视频制作组", - "topology": "star", - "config": { - "allow_self_leave": true, - "requires_approval": false, - "consensus_required": false, - "consensus_threshold": 0.5, - "broadcast_mode": "all" - }, - "initial_members": [ - { - "agent_id": "worker-1", - "system_id": "sys-a", - "endpoint": "http://worker1/synapse" - } - ], - "roles": [ - { - "id": "coordinator", - "name": "协调者", - "permissions": ["create", "disband", "split", "vote"], - "max_tasks": 10 - } - ] - } -} -``` - -### 10.2 GroupTaskSplitPayload(任务拆分) - -```json -{ - "original_task": { - "id": "task-xxx", - "type": "video_generation", - "requirements": { - "script": "xxx", - "duration": 60 - }, - "deadline": "2026-01-01T00:10:00Z" - }, - "subtasks": [ - { - "id": "sub-1", - "description": "生成脚本", - "assigned_to": "writer-agent", - "dependencies": [], - "estimated_duration": 120, - "priority": 1 - }, - { - "id": "sub-2", - "description": "生成配音", - "assigned_to": "voice-agent", - "dependencies": ["sub-1"], - "estimated_duration": 180, - "priority": 2 - } - ], - "merge_strategy": "all_success" -} -``` - -### 10.3 GroupTaskMergePayload(结果合并) - -```json -{ - "original_task_id": "task-xxx", - "subtask_results": [ - { - "subtask_id": "sub-1", - "assigned_to": "writer-agent", - "status": "success", - "result": { "script": "..." }, - "completed_at": "2026-01-01T00:02:00Z" - } - ], - "merge_strategy_used": "all_success", - "merged_result": { - "video_url": "http://..." - }, - "consensus_achieved": true -} -``` - -### 10.4 GroupVotePayload(投票) - -```json -{ - "vote_id": "vote-xxx", - "question": "是否采用方案A?", - "options": ["方案A", "方案B", "方案C"], - "voters": ["agent-1", "agent-2", "agent-3"], - "deadline": "2026-01-01T00:05:00Z", - "threshold": 0.66, - "status": "open", - "votes": [] -} -``` - -### 10.5 GroupConsensusEscalatePayload(共识升级) - -```json -{ - "vote_id": "vote-xxx", - "escalation_id": "esc-xxx", - "question": "是否采用方案A?", - "votes": [ - { - "voter_id": "agent-1", - "voter_role": "reviewer", - "option": "方案A", - "reason": "质量更好" - } - ], - "consensus_status": { - "required_threshold": 0.66, - "actual_threshold": 0.33, - "leading_option": "方案A", - "options_tied": false - }, - "escalate_reason": { - "code": "no_consensus", - "message": "无法达成共识" - }, - "escalation_level": 2, - "deadline": "2026-01-01T00:10:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 11. 数据结构 - -### 11.1 AgentGroup(群组) - -```go -type AgentGroup struct { - ID string - Name string - Topology GroupTopology - CreatedBy string - CreatedAt Timestamp - Config GroupConfig - Members []GroupMember - Roles []GroupRole - Status GroupStatus -} -``` - -### 11.2 GroupMember(群组成员) - -```go -type GroupMember struct { - AgentID string - AgentName string - Role string - JoinedAt Timestamp - Status GroupMemberStatus - Capabilities []string - LoadFactor float64 // 负载因子 0-1,用于任务分配 -} -``` - -### 11.3 Subtask(子任务) - -```go -type Subtask struct { - ID string - Description string - AssignedTo string - Dependencies []string - EstimatedDuration int - Priority int -} -``` - ---- - -## 12. 错误码 - -群组协议特有错误码: - -| 错误码 | 说明 | -|--------|------| -| `group_not_found` | 群组不存在 | -| `group_not_active` | 群组不活跃 | -| `group_full` | 群组已满 | -| `already_member` | 已是成员 | -| `not_group_member` | 不是群组成员 | -| `member_not_found` | 成员不存在 | -| `permission_denied` | 权限不足 | -| `invalid_params` | 参数无效 | - ---- - -## 13. 参考实现 - -本协议的参考实现位于 `group/` 目录: - -| 文件 | 说明 | -|------|------| -| [group/protocol.go](../group/protocol.go) | 群组协议核心实现 | -| [types/types.go](../types/types.go) | 群组相关数据类型 | - ---- - -## 附录 A:与 A2A 协议的关系 - -- 群组内的点对点通信使用 A2A 协议 -- 群组协议在 A2A 协议之上提供群组管理、任务拆分合并、共识投票等能力 -- 群组消息同样使用统一消息信封(`UnifiedSynapseMessage`),通过 `group_id` 字段标识群组上下文 diff --git a/docs/03-group-protocol.md b/docs/03-group-protocol.md deleted file mode 100644 index a6bbf9a..0000000 --- a/docs/03-group-protocol.md +++ /dev/null @@ -1,545 +0,0 @@ -# A2N 协议(Agent-to-N Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-a2a-raw-protocol.md) - ---- - -## 1. 概述 - -A2N(Agent-to-N)组群协议定义了多个 Agent 组成群组进行协同工作的完整规范,包括群组管理、任务拆分与合并、群体决策、角色与权限等。 - -### 1.1 适用场景 -- 复杂任务的拆分与并行执行(MapReduce 模式) -- 多 Agent 协同完成单一目标 -- 群体投票与共识决策 -- 临时或永久的 Agent 工作组 -- 分级升级(escalation)机制 - -### 1.2 依赖 -- 依赖 A2A 协议的点对点通信能力 -- 群组内成员间的单播通信使用 A2A 协议 - ---- - -## 2. 核心概念 - -### 2.1 Group(群组) -由多个 Agent 组成的协作单元,具有明确的拓扑结构、角色分工与协作规则。 - -### 2.2 Topology(拓扑结构) - -| 拓扑类型 | 说明 | 适用场景 | -|---------|------|---------| -| `star` | 星型,中心 coordinator 协调 | 简单任务分发 | -| `mesh` | 网状,成员间可直接通信 | 对等协作 | -| `chain` | 链式,流水线模式 | 顺序处理 | -| `hierarchical` | 层级型,多层管理 | 大型复杂任务 | -| `fullmesh` | 全连接网状 | 高可靠协作 | - -### 2.3 Role(角色) - -| 角色 | 说明 | 权限 | -|------|------|------| -| `coordinator` | 协调者 | 创建/解散群组、任务拆分、发起投票 | -| `worker` | 工作者 | 执行子任务、提交结果 | -| `reviewer` | 审核者 | 审核结果、发起投票 | -| `observer` | 观察者 | 只读,查看进度 | - -### 2.4 GroupStatus(群组状态) - -| 状态 | 说明 | -|------|------| -| `creating` | 创建中 | -| `active` | 活跃 | -| `frozen` | 冻结(不可执行新任务) | -| `disbanded` | 已解散(终态) | - ---- - -## 3. 消息类型 - -### 3.1 消息类型清单 - -所有消息类型前缀:`group:` 或 `inter_group:` - -#### 群组管理 - -| 消息类型 | 说明 | -|---------|------| -| `group:create` | 创建群组 | -| `group:disband` | 解散群组 | -| `group:join` | 加入群组 | -| `group:leave` | 离开群组 | -| `group:invite` | 邀请加入 | -| `group:accept_invite` | 接受邀请 | -| `group:reject_invite` | 拒绝邀请 | -| `group:member_update` | 成员更新通知 | -| `group:role_change` | 角色变更 | - -#### 群组通信 - -| 消息类型 | 说明 | -|---------|------| -| `group:broadcast` | 广播(所有成员) | -| `group:multicast` | 组播(指定成员) | -| `group:direct` | 群内单播 | -| `group:relay` | 消息中继 | - -#### 任务协作 - -| 消息类型 | 说明 | -|---------|------| -| `group:task_split` | 任务拆分 | -| `group:task_assign` | 任务分配 | -| `group:task_merge` | 结果合并 | -| `group:task_progress` | 子任务进度 | - -#### 共识与投票 - -| 消息类型 | 说明 | -|---------|------| -| `group:vote` | 发起投票 | -| `group:vote_submit` | 提交投票 | -| `group:consensus` | 达成共识 | - -#### 人在回路(HiL) - -| 消息类型 | 说明 | -|---------|------| -| `group:consensus_escalate` | 共识僵局升级给人类 | -| `group:subtask_escalate` | 子任务阻塞升级给人类 | -| `group:human_decision` | 人类决策结果 | -| `inter_group:escalate` | 跨群组升级 | - -**完整定义:** [types/types.go](../types/types.go) - ---- - -## 4. 群组生命周期 - -### 4.1 状态机 - -``` -creating → active → frozen → disbanded - ↑ ↓ - └─────────┘ - 解冻 -``` - -### 4.2 群组创建流程 - -``` -创建者 被邀请成员 - | | - |------ group:invite -------------->| 发送邀请 - | | - |<----- group:accept_invite --------| 接受邀请 - | | - |------ group:member_update ------->| 通知成员更新 - | | - [群组创建完成,状态变为 active] | -``` - -### 4.3 群组解散流程 - -``` -coordinator 所有成员 - | | - |------ group:disband ------------->| 通知解散 - | | - [群组状态变为 disbanded] | -``` - ---- - -## 5. 任务协作流程 - -### 5.1 MapReduce 模式(拆分-执行-合并) - -``` - ┌──────────────┐ - │ coordinator │ - └──────┬───────┘ - │ - group:task_split(拆分任务) - │ - ┌────────────────┼────────────────┐ - ▼ ▼ ▼ - ┌─────────┐ ┌─────────┐ ┌─────────┐ - │ worker1 │ │ worker2 │ │ worker3 │ - └────┬────┘ └────┬────┘ └────┬────┘ - │ │ │ - │ 执行子任务 │ 执行子任务 │ 执行子任务 - │ │ │ - ▼ ▼ ▼ - 子任务结果 子任务结果 子任务结果 - └────────────────┼────────────────┘ - │ - group:task_merge(合并结果) - ▼ - ┌──────────────┐ - │ 最终结果 │ - └──────────────┘ -``` - -### 5.2 详细流程 - -1. **任务拆分阶段** - - coordinator 接收原始任务 - - 将任务拆分为多个子任务(subtask) - - 为每个子任务指定执行的 worker - - 定义合并策略(merge strategy) - -2. **并行执行阶段** - - 各 worker 并行执行子任务 - - 定期上报进度(`group:task_progress`) - - 子任务完成后上报结果 - -3. **结果合并阶段** - - 所有子任务完成后,coordinator 合并结果 - - 根据合并策略决定最终结果 - - 输出最终结果 - ---- - -## 6. 合并策略(Merge Strategy) - -| 策略 | 说明 | -|------|------| -| `all_success` | 全部成功才认为成功,否则失败 | -| `majority` | 多数子任务成功即可,取多数结果 | -| `any_complete` | 任意一个完成即返回结果 | -| `priority` | 按优先级,高优先级子任务结果优先 | - ---- - -## 7. 投票与共识 - -### 7.1 投票流程 - -``` -发起者 投票者 - | | - |-------- group:vote -------------->| 发起投票 - | | - |<------- group:vote_submit --------| 提交投票 - | | - [计票,判断是否达到阈值] | - | | - |-------- group:consensus --------->| 公布结果 - | | -``` - -### 7.2 投票规则 - -- `threshold`:通过阈值(0-1),如 0.5 表示过半 -- `deadline`:投票截止时间 -- `voters`:有投票权的成员列表 -- 超时未投票视为弃权 - -### 7.3 共识僵局(Consensus Deadlock) - -当投票无法达成共识(如平票、未达阈值且超时)时,可升级给人类决策。 - ---- - -## 8. 人在回路(HiL) - -群组协作中有两种升级场景: - -### 8.1 共识僵局升级 -投票无法达成共识时,升级给人类裁决。 - -**消息:** `group:consensus_escalate` - -### 8.2 子任务阻塞升级 -某个子任务遇到无法自动解决的问题时,升级给人类。 - -**消息:** `group:subtask_escalate` - -### 8.3 跨群组升级 -问题超出当前群组能力时,可升级到上级群组或人类。 - -**消息:** `inter_group:escalate` - ---- - -## 9. 接口规范 - -### 9.1 GroupProtocol 接口 - -```go -type GroupProtocol interface { - // 处理群组消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h GroupTaskHandler) - - // 查询群组列表 - GetGroups() []*AgentGroup - - // 查询特定群组 - GetGroup(groupID string) (*AgentGroup, bool) -} -``` - -**参考实现:** [group/protocol.go](../group/protocol.go) - -### 9.2 GroupTaskHandler 接口 - -```go -type GroupTaskHandler interface { - // 执行子任务 - ExecuteSubtask(ctx context.Context, subtaskID string, payload map[string]interface{}) (any, error) - - // 合并多个子任务结果 - MergeResults(results []SubtaskResult, strategy MergeStrategy) (any, error) - - // 验证任务是否可拆分,返回拆分方案 - ValidateTaskSplit(taskType string, requirements map[string]interface{}) ([]Subtask, bool) -} -``` - -**说明:** -- `ExecuteSubtask`:执行单个子任务的业务逻辑 -- `MergeResults`:根据策略合并多个子任务的结果 -- `ValidateTaskSplit`:验证任务是否可拆分,并给出拆分方案 - -### 9.3 配置项 - -```go -type GroupConfig struct { - MaxGroupSize int // 最大群组人数(默认 20) - MaxSubtasks int // 最大子任务数(默认 50) - ConsensusTimeout time.Duration // 共识超时(默认 5 分钟) - TaskTimeout time.Duration // 任务超时(默认 10 分钟) -} -``` - ---- - -## 10. 载荷格式 - -### 10.1 GroupCreatePayload(创建群组) - -```json -{ - "group": { - "name": "视频制作组", - "topology": "star", - "config": { - "allow_self_leave": true, - "requires_approval": false, - "consensus_required": false, - "consensus_threshold": 0.5, - "broadcast_mode": "all" - }, - "initial_members": [ - { - "agent_id": "worker-1", - "system_id": "sys-a", - "endpoint": "http://worker1/synapse" - } - ], - "roles": [ - { - "id": "coordinator", - "name": "协调者", - "permissions": ["create", "disband", "split", "vote"], - "max_tasks": 10 - } - ] - } -} -``` - -### 10.2 GroupTaskSplitPayload(任务拆分) - -```json -{ - "original_task": { - "id": "task-xxx", - "type": "video_generation", - "requirements": { - "script": "xxx", - "duration": 60 - }, - "deadline": "2026-01-01T00:10:00Z" - }, - "subtasks": [ - { - "id": "sub-1", - "description": "生成脚本", - "assigned_to": "writer-agent", - "dependencies": [], - "estimated_duration": 120, - "priority": 1 - }, - { - "id": "sub-2", - "description": "生成配音", - "assigned_to": "voice-agent", - "dependencies": ["sub-1"], - "estimated_duration": 180, - "priority": 2 - } - ], - "merge_strategy": "all_success" -} -``` - -### 10.3 GroupTaskMergePayload(结果合并) - -```json -{ - "original_task_id": "task-xxx", - "subtask_results": [ - { - "subtask_id": "sub-1", - "assigned_to": "writer-agent", - "status": "success", - "result": { "script": "..." }, - "completed_at": "2026-01-01T00:02:00Z" - } - ], - "merge_strategy_used": "all_success", - "merged_result": { - "video_url": "http://..." - }, - "consensus_achieved": true -} -``` - -### 10.4 GroupVotePayload(投票) - -```json -{ - "vote_id": "vote-xxx", - "question": "是否采用方案A?", - "options": ["方案A", "方案B", "方案C"], - "voters": ["agent-1", "agent-2", "agent-3"], - "deadline": "2026-01-01T00:05:00Z", - "threshold": 0.66, - "status": "open", - "votes": [] -} -``` - -### 10.5 GroupConsensusEscalatePayload(共识升级) - -```json -{ - "vote_id": "vote-xxx", - "escalation_id": "esc-xxx", - "question": "是否采用方案A?", - "votes": [ - { - "voter_id": "agent-1", - "voter_role": "reviewer", - "option": "方案A", - "reason": "质量更好" - } - ], - "consensus_status": { - "required_threshold": 0.66, - "actual_threshold": 0.33, - "leading_option": "方案A", - "options_tied": false - }, - "escalate_reason": { - "code": "no_consensus", - "message": "无法达成共识" - }, - "escalation_level": 2, - "deadline": "2026-01-01T00:10:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 11. 数据结构 - -### 11.1 AgentGroup(群组) - -```go -type AgentGroup struct { - ID string - Name string - Topology GroupTopology - CreatedBy string - CreatedAt Timestamp - Config GroupConfig - Members []GroupMember - Roles []GroupRole - Status GroupStatus -} -``` - -### 11.2 GroupMember(群组成员) - -```go -type GroupMember struct { - AgentID string - AgentName string - Role string - JoinedAt Timestamp - Status GroupMemberStatus - Capabilities []string - LoadFactor float64 // 负载因子 0-1,用于任务分配 -} -``` - -### 11.3 Subtask(子任务) - -```go -type Subtask struct { - ID string - Description string - AssignedTo string - Dependencies []string - EstimatedDuration int - Priority int -} -``` - ---- - -## 12. 错误码 - -群组协议特有错误码: - -| 错误码 | 说明 | -|--------|------| -| `group_not_found` | 群组不存在 | -| `group_not_active` | 群组不活跃 | -| `group_full` | 群组已满 | -| `already_member` | 已是成员 | -| `not_group_member` | 不是群组成员 | -| `member_not_found` | 成员不存在 | -| `permission_denied` | 权限不足 | -| `invalid_params` | 参数无效 | - ---- - -## 13. 参考实现 - -本协议的参考实现位于 `group/` 目录: - -| 文件 | 说明 | -|------|------| -| [group/protocol.go](../group/protocol.go) | 群组协议核心实现 | -| [types/types.go](../types/types.go) | 群组相关数据类型 | - ---- - -## 附录 A:与 A2A 协议的关系 - -- 群组内的点对点通信使用 A2A 协议 -- 群组协议在 A2A 协议之上提供群组管理、任务拆分合并、共识投票等能力 -- 群组消息同样使用统一消息信封(`UnifiedSynapseMessage`),通过 `group_id` 字段标识群组上下文 diff --git a/docs/04-caller-protocol.md b/docs/04-caller-protocol.md deleted file mode 100644 index 7de3bd7..0000000 --- a/docs/04-caller-protocol.md +++ /dev/null @@ -1,503 +0,0 @@ -# P2A 协议(Person/Program-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-a2a-raw-protocol.md) - ---- - -## 1. 概述 - -P2A(Person/Program-to-Agent)调用协议定义了**非 Agent 调用方**(如普通后端服务、前端应用、第三方系统、人类用户)如何调用 Agent 能力的规范。 - -本协议将 A2A 协议的复杂性封装起来,提供简洁的 RESTful API,使调用方无需了解 A2A 协议细节即可使用 Agent 能力。 - -### 1.1 适用场景 -- 前端应用直接调用 Agent 能力 -- 后端业务系统集成 Agent 服务 -- 第三方开发者通过 API 接入 -- 无需实现完整 A2A 协议的调用方 - -### 1.2 设计原则 -- **简单易用**:标准 RESTful API,JSON 格式 -- **两种模式**:回调模式 + 轮询模式,调用方按需选择 -- **认证简单**:API Key 认证,无需 HMAC 签名 -- **文件支持**:支持 multipart/form-data 上传文件 -- **错误友好**:清晰的错误码和错误信息 - -### 1.3 与 A2A 协议的关系 - -``` -外部调用方 ──P2A 协议──▶ External API Layer ──A2A 协议──▶ Agent -``` - -P2A 协议是 A2A 协议的"简化入口",所有请求最终会转换为 灵隙消息发送给 Agent。 - ---- - -## 2. 认证方式 - -### 2.1 API Key 认证 -- 在 HTTP Header 中传递:`X-API-Key: {api_key}` -- 或在 URL Query 中传递:`?api_key={api_key}` -- 如果服务端未配置 API Key,则跳过认证 - -### 2.2 回调验证(可选) -如果调用方提供了 `callback_token`,则服务端在回调时会在 Header 中带上 `X-Callback-Token`,用于调用方验证回调来源。 - ---- - -## 3. API 端点 - -所有端点默认前缀:`/api/v1/synapse` - -### 3.1 端点清单 - -| 方法 | 路径 | 说明 | -|------|------|------| -| POST | `/task` | 提交任务(JSON) | -| POST | `/task/multipart` | 提交任务(带文件上传) | -| GET | `/task/{task_id}` | 获取任务详情 | -| GET | `/task/{task_id}/status` | 获取任务状态(简化版) | -| GET | `/tasks` | 获取任务列表 | -| POST | `/task/{task_id}/cancel` | 取消任务 | -| GET | `/capabilities` | 获取能力清单 | -| POST | `/callback` | 接收回调(调用方实现) | - ---- - -## 4. 任务提交 - -### 4.1 提交任务(JSON) - -**请求:** -```http -POST /api/v1/synapse/task -Content-Type: application/json -X-API-Key: your-api-key - -{ - "task_type": "text_generation", - "payload": { - "prompt": "写一首诗", - "style": "古典" - }, - "external_task_id": "my-task-001", - "priority": "normal", - "callback_url": "https://your-domain.com/callback", - "callback_token": "your-callback-token" -} -``` - -**请求字段说明:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型,如 `video_generation`, `image_generation` | -| `payload` | object | 是 | 任务参数,具体结构取决于 task_type | -| `external_task_id` | string | 否 | 调用方的任务 ID,用于关联 | -| `priority` | string | 否 | 优先级:`low`, `normal`, `high`, `urgent`,默认 `normal` | -| `callback_url` | string | 否 | 回调 URL,不提供则需轮询 | -| `callback_token` | string | 否 | 回调验证 token | - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "received", - "message": "任务已接收" -} -``` - -**响应字段说明:** - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | bool | 是否成功 | -| `task_id` | string | 服务端生成的任务 ID | -| `status` | string | 初始状态,通常为 `received` | -| `message` | string | 提示信息 | -| `error` | string | 错误信息(失败时) | - -### 4.2 提交任务(Multipart 带文件) - -**请求:** -```http -POST /api/v1/synapse/task/multipart -Content-Type: multipart/form-data -X-API-Key: your-api-key - -------WebKitFormBoundary -Content-Disposition: form-data; name="task_type" - -image_generation - -------WebKitFormBoundary -Content-Disposition: form-data; name="payload" - -{"prompt":"一只猫","style":"写实"} - -------WebKitFormBoundary -Content-Disposition: form-data; name="priority" - -normal - -------WebKitFormBoundary -Content-Disposition: form-data; name="file"; filename="reference.jpg" -Content-Type: image/jpeg - -[二进制数据] - -------WebKitFormBoundary-- -``` - -**表单字段:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型 | -| `payload` | string(JSON) | 是 | 任务参数(JSON 字符串) | -| `external_task_id` | string | 否 | 外部任务 ID | -| `priority` | string | 否 | 优先级 | -| `callback_url` | string | 否 | 回调 URL | -| `callback_token` | string | 否 | 回调 token | -| `file` | file | 否 | 上传的文件(可多个) | - -**响应:** 同 JSON 提交方式 - ---- - -## 5. 任务查询 - -### 5.1 获取任务详情 - -**请求:** -```http -GET /api/v1/synapse/task/{task_id} -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task": { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z", - "completed_at": "2026-01-01T00:01:00Z", - "eta": "2026-01-01T00:01:00Z", - "result": { - "text": "生成的文本...", - "metadata": { "tokens": 1024 } - }, - "error": null, - "external_task_id": "my-task-001" - } -} -``` - -**任务状态:** - -| 状态 | 说明 | -|------|------| -| `received` | 已接收 | -| `processing` | 处理中 | -| `completed` | 已完成 | -| `failed` | 已失败 | -| `cancelled` | 已取消 | - -### 5.2 获取任务状态(简化版) - -**请求:** -```http -GET /api/v1/synapse/task/{task_id}/status -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "processing", - "progress": 50 -} -``` - -### 5.3 获取任务列表 - -**请求:** -```http -GET /api/v1/synapse/tasks?status=processing&limit=20&offset=0 -X-API-Key: your-api-key -``` - -**查询参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `status` | string | 否 | 按状态过滤 | -| `limit` | int | 否 | 每页数量,默认 20 | -| `offset` | int | 否 | 偏移量,默认 0 | - -**响应:** -```json -{ - "success": true, - "tasks": [ - { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z" - } - ], - "total": 1, - "limit": 20, - "offset": 0, - "has_more": false -} -``` - ---- - -## 6. 任务取消 - -**请求:** -```http -POST /api/v1/synapse/task/{task_id}/cancel -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "cancelled", - "message": "任务已取消" -} -``` - ---- - -## 7. 能力查询 - -**请求:** -```http -GET /api/v1/synapse/capabilities -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "capabilities": { - "agent_id": "my-agent", - "agent_name": "我的Agent", - "system_id": "my-system", - "protocol_version": "1.0.0", - "supported_task_types": [ - { - "type": "text_generation", - "name": "文本生成", - "description": "生成各种类型的文本内容", - "estimated_time": "30s", - "input_schema": "...", - "output_schema": "..." - } - ], - "supported_transport_modes": ["callback", "polling"], - "max_file_size": 104857600, - "max_concurrent_tasks": 10, - "support_progress_updates": true, - "support_streaming": false, - "support_hil": true, - "support_groups": true - } -} -``` - ---- - -## 8. 回调机制 - -如果调用方提供了 `callback_url`,服务端会在任务状态变化时主动回调。 - -### 8.1 回调请求 - -```http -POST {callback_url} -Content-Type: application/json -X-Callback-Token: {callback_token} - -{ - "task_id": "task-abc123", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "result": { - "text": "生成的文本..." - }, - "error": null, - "timestamp": "2026-01-01T00:01:00Z" -} -``` - -### 8.2 回调类型 - -| 触发时机 | 说明 | -|---------|------| -| 任务开始处理 | `status=processing`, `progress=0` | -| 进度更新 | `status=processing`, `progress=N` | -| 任务完成 | `status=completed`, `progress=100`, 包含 result | -| 任务失败 | `status=failed`, 包含 error | -| 任务取消 | `status=cancelled` | - -### 8.3 回调响应 - -调用方应返回 2xx 状态码表示成功接收。如果返回非 2xx,服务端会重试(指数退避,最多 5 次)。 - ---- - -## 9. 错误处理 - -### 9.1 错误响应格式 - -```json -{ - "success": false, - "error": "invalid_task_type", - "message": "不支持的任务类型" -} -``` - -### 9.2 错误码列表 - -| 错误码 | HTTP 状态码 | 说明 | -|--------|------------|------| -| `unauthorized` | 401 | API Key 无效或缺失 | -| `invalid_request` | 400 | 请求格式无效 | -| `invalid_task_type` | 400 | 任务类型不支持 | -| `invalid_params` | 400 | 参数无效 | -| `task_not_found` | 404 | 任务不存在 | -| `task_already_completed` | 409 | 任务已完成,无法取消 | -| `file_too_large` | 413 | 文件过大 | -| `rate_limited` | 429 | 请求过于频繁 | -| `internal_error` | 500 | 服务内部错误 | -| `service_unavailable` | 503 | 服务不可用 | - ---- - -## 10. SDK 客户端接口 - -为方便调用方集成,提供 SDK 客户端。 - -### 10.1 SDK 初始化 - -```go -client := sdk.NewClient(sdk.ClientConfig{ - BaseURL: "https://agent-api.example.com", - APIKey: "your-api-key", - Timeout: 30 * time.Second, -}) -``` - -### 10.2 SDK 方法清单 - -| 方法 | 说明 | -|------|------| -| `SubmitTask(ctx, req)` | 提交任务(JSON) | -| `SubmitTaskWithFiles(ctx, req, files)` | 提交任务(带文件) | -| `GetTask(ctx, taskID)` | 获取任务详情 | -| `GetTaskStatus(ctx, taskID)` | 获取任务状态 | -| `ListTasks(ctx, status, limit, offset)` | 获取任务列表 | -| `CancelTask(ctx, taskID)` | 取消任务 | -| `GetCapabilities(ctx)` | 获取能力清单 | -| `WaitForTask(ctx, taskID, interval)` | 等待任务完成(轮询) | - -### 10.3 数据结构 - -```go -type TaskRequest struct { - TaskType string - Payload map[string]any - ExternalTaskID string - Priority string - CallbackURL string - CallbackToken string -} - -type TaskInfo struct { - ID string - Type string - Status string - Progress int - Message string - CreatedAt string - UpdatedAt string - CompletedAt string - ETA string - Result map[string]any - Error *TaskError - ExternalTaskID string -} -``` - -**完整 SDK 实现:** [sdk/client.go](../sdk/client.go) - ---- - -## 11. 参考实现 - -本协议的参考实现: - -| 模块 | 文件路径 | 说明 | -|------|---------|------| -| 服务端 | [externalapi/handler.go](../externalapi/handler.go) | External API Handler | -| 客户端 SDK | [sdk/client.go](../sdk/client.go) | Go 语言 SDK | - ---- - -## 附录 A:调用模式选择 - -### 回调模式 vs 轮询模式 - -| 对比项 | 回调模式 | 轮询模式 | -|--------|---------|---------| -| 实时性 | 高,状态变化即时通知 | 低,取决于轮询间隔 | -| 实现复杂度 | 调用方需提供公网可访问的回调接口 | 简单,只需调用 GET 接口 | -| 网络要求 | 调用方需要公网可达 | 只需调用方能访问服务端 | -| 适用场景 | 生产环境、需要实时通知 | 开发测试、内网环境 | - -### 选择建议 - -- **有公网服务器**:使用回调模式 -- **本地开发 / 内网环境**:使用轮询模式 -- **长时间任务**:建议回调模式,避免频繁轮询 -- **短任务(<10s)**:可直接同步等待或高频轮询 - ---- - -## 附录 B:从 A2A 协议到 P2A 协议的映射 - -| 灵隙概念 | P2A 对应 | 说明 | -|---------|---------|------| -| `p2p:task_request` | `POST /task` | 任务提交 | -| `p2p:task_status_update` | 回调 / GET /task | 状态更新 | -| `p2p:task_complete` | 回调(status=completed) | 任务完成 | -| `p2p:task_failed` | 回调(status=failed) | 任务失败 | -| `p2p:task_cancel` | `POST /task/{id}/cancel` | 任务取消 | -| `p2p:capability_query` | `GET /capabilities` | 能力查询 | -| Agent 身份 | API Key | 简化认证 | -| HMAC 签名 | Callback Token | 简化验证 | diff --git a/docs/04-p2a-protocol.md b/docs/04-p2a-protocol.md deleted file mode 100644 index 70dc4ac..0000000 --- a/docs/04-p2a-protocol.md +++ /dev/null @@ -1,503 +0,0 @@ -# P2A 协议(Person/Program-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -P2A(Person/Program-to-Agent)调用协议定义了**非 Agent 调用方**(如普通后端服务、前端应用、第三方系统、人类用户)如何调用 Agent 能力的规范。 - -本协议将 A2A 协议的复杂性封装起来,提供简洁的 RESTful API,使调用方无需了解 A2A 协议细节即可使用 Agent 能力。 - -### 1.1 适用场景 -- 前端应用直接调用 Agent 能力 -- 后端业务系统集成 Agent 服务 -- 第三方开发者通过 API 接入 -- 无需实现完整 A2A 协议的调用方 - -### 1.2 设计原则 -- **简单易用**:标准 RESTful API,JSON 格式 -- **两种模式**:回调模式 + 轮询模式,调用方按需选择 -- **认证简单**:API Key 认证,无需 HMAC 签名 -- **文件支持**:支持 multipart/form-data 上传文件 -- **错误友好**:清晰的错误码和错误信息 - -### 1.3 与 A2A 协议的关系 - -``` -外部调用方 ──P2A 协议──▶ External API Layer ──A2A 协议──▶ Agent -``` - -P2A 协议是 A2A 协议的"简化入口",所有请求最终会转换为 灵隙消息发送给 Agent。 - ---- - -## 2. 认证方式 - -### 2.1 API Key 认证 -- 在 HTTP Header 中传递:`X-API-Key: {api_key}` -- 或在 URL Query 中传递:`?api_key={api_key}` -- 如果服务端未配置 API Key,则跳过认证 - -### 2.2 回调验证(可选) -如果调用方提供了 `callback_token`,则服务端在回调时会在 Header 中带上 `X-Callback-Token`,用于调用方验证回调来源。 - ---- - -## 3. API 端点 - -所有端点默认前缀:`/api/v1/synapse` - -### 3.1 端点清单 - -| 方法 | 路径 | 说明 | -|------|------|------| -| POST | `/task` | 提交任务(JSON) | -| POST | `/task/multipart` | 提交任务(带文件上传) | -| GET | `/task/{task_id}` | 获取任务详情 | -| GET | `/task/{task_id}/status` | 获取任务状态(简化版) | -| GET | `/tasks` | 获取任务列表 | -| POST | `/task/{task_id}/cancel` | 取消任务 | -| GET | `/capabilities` | 获取能力清单 | -| POST | `/callback` | 接收回调(调用方实现) | - ---- - -## 4. 任务提交 - -### 4.1 提交任务(JSON) - -**请求:** -```http -POST /api/v1/synapse/task -Content-Type: application/json -X-API-Key: your-api-key - -{ - "task_type": "text_generation", - "payload": { - "prompt": "写一首诗", - "style": "古典" - }, - "external_task_id": "my-task-001", - "priority": "normal", - "callback_url": "https://your-domain.com/callback", - "callback_token": "your-callback-token" -} -``` - -**请求字段说明:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型,如 `video_generation`, `image_generation` | -| `payload` | object | 是 | 任务参数,具体结构取决于 task_type | -| `external_task_id` | string | 否 | 调用方的任务 ID,用于关联 | -| `priority` | string | 否 | 优先级:`low`, `normal`, `high`, `urgent`,默认 `normal` | -| `callback_url` | string | 否 | 回调 URL,不提供则需轮询 | -| `callback_token` | string | 否 | 回调验证 token | - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "received", - "message": "任务已接收" -} -``` - -**响应字段说明:** - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | bool | 是否成功 | -| `task_id` | string | 服务端生成的任务 ID | -| `status` | string | 初始状态,通常为 `received` | -| `message` | string | 提示信息 | -| `error` | string | 错误信息(失败时) | - -### 4.2 提交任务(Multipart 带文件) - -**请求:** -```http -POST /api/v1/synapse/task/multipart -Content-Type: multipart/form-data -X-API-Key: your-api-key - -------WebKitFormBoundary -Content-Disposition: form-data; name="task_type" - -image_generation - -------WebKitFormBoundary -Content-Disposition: form-data; name="payload" - -{"prompt":"一只猫","style":"写实"} - -------WebKitFormBoundary -Content-Disposition: form-data; name="priority" - -normal - -------WebKitFormBoundary -Content-Disposition: form-data; name="file"; filename="reference.jpg" -Content-Type: image/jpeg - -[二进制数据] - -------WebKitFormBoundary-- -``` - -**表单字段:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型 | -| `payload` | string(JSON) | 是 | 任务参数(JSON 字符串) | -| `external_task_id` | string | 否 | 外部任务 ID | -| `priority` | string | 否 | 优先级 | -| `callback_url` | string | 否 | 回调 URL | -| `callback_token` | string | 否 | 回调 token | -| `file` | file | 否 | 上传的文件(可多个) | - -**响应:** 同 JSON 提交方式 - ---- - -## 5. 任务查询 - -### 5.1 获取任务详情 - -**请求:** -```http -GET /api/v1/synapse/task/{task_id} -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task": { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z", - "completed_at": "2026-01-01T00:01:00Z", - "eta": "2026-01-01T00:01:00Z", - "result": { - "text": "生成的文本...", - "metadata": { "tokens": 1024 } - }, - "error": null, - "external_task_id": "my-task-001" - } -} -``` - -**任务状态:** - -| 状态 | 说明 | -|------|------| -| `received` | 已接收 | -| `processing` | 处理中 | -| `completed` | 已完成 | -| `failed` | 已失败 | -| `cancelled` | 已取消 | - -### 5.2 获取任务状态(简化版) - -**请求:** -```http -GET /api/v1/synapse/task/{task_id}/status -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "processing", - "progress": 50 -} -``` - -### 5.3 获取任务列表 - -**请求:** -```http -GET /api/v1/synapse/tasks?status=processing&limit=20&offset=0 -X-API-Key: your-api-key -``` - -**查询参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `status` | string | 否 | 按状态过滤 | -| `limit` | int | 否 | 每页数量,默认 20 | -| `offset` | int | 否 | 偏移量,默认 0 | - -**响应:** -```json -{ - "success": true, - "tasks": [ - { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z" - } - ], - "total": 1, - "limit": 20, - "offset": 0, - "has_more": false -} -``` - ---- - -## 6. 任务取消 - -**请求:** -```http -POST /api/v1/synapse/task/{task_id}/cancel -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "cancelled", - "message": "任务已取消" -} -``` - ---- - -## 7. 能力查询 - -**请求:** -```http -GET /api/v1/synapse/capabilities -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "capabilities": { - "agent_id": "my-agent", - "agent_name": "我的Agent", - "system_id": "my-system", - "protocol_version": "1.0.0", - "supported_task_types": [ - { - "type": "text_generation", - "name": "文本生成", - "description": "生成各种类型的文本内容", - "estimated_time": "30s", - "input_schema": "...", - "output_schema": "..." - } - ], - "supported_transport_modes": ["callback", "polling"], - "max_file_size": 104857600, - "max_concurrent_tasks": 10, - "support_progress_updates": true, - "support_streaming": false, - "support_hil": true, - "support_groups": true - } -} -``` - ---- - -## 8. 回调机制 - -如果调用方提供了 `callback_url`,服务端会在任务状态变化时主动回调。 - -### 8.1 回调请求 - -```http -POST {callback_url} -Content-Type: application/json -X-Callback-Token: {callback_token} - -{ - "task_id": "task-abc123", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "result": { - "text": "生成的文本..." - }, - "error": null, - "timestamp": "2026-01-01T00:01:00Z" -} -``` - -### 8.2 回调类型 - -| 触发时机 | 说明 | -|---------|------| -| 任务开始处理 | `status=processing`, `progress=0` | -| 进度更新 | `status=processing`, `progress=N` | -| 任务完成 | `status=completed`, `progress=100`, 包含 result | -| 任务失败 | `status=failed`, 包含 error | -| 任务取消 | `status=cancelled` | - -### 8.3 回调响应 - -调用方应返回 2xx 状态码表示成功接收。如果返回非 2xx,服务端会重试(指数退避,最多 5 次)。 - ---- - -## 9. 错误处理 - -### 9.1 错误响应格式 - -```json -{ - "success": false, - "error": "invalid_task_type", - "message": "不支持的任务类型" -} -``` - -### 9.2 错误码列表 - -| 错误码 | HTTP 状态码 | 说明 | -|--------|------------|------| -| `unauthorized` | 401 | API Key 无效或缺失 | -| `invalid_request` | 400 | 请求格式无效 | -| `invalid_task_type` | 400 | 任务类型不支持 | -| `invalid_params` | 400 | 参数无效 | -| `task_not_found` | 404 | 任务不存在 | -| `task_already_completed` | 409 | 任务已完成,无法取消 | -| `file_too_large` | 413 | 文件过大 | -| `rate_limited` | 429 | 请求过于频繁 | -| `internal_error` | 500 | 服务内部错误 | -| `service_unavailable` | 503 | 服务不可用 | - ---- - -## 10. SDK 客户端接口 - -为方便调用方集成,提供 SDK 客户端。 - -### 10.1 SDK 初始化 - -```go -client := sdk.NewClient(sdk.ClientConfig{ - BaseURL: "https://agent-api.example.com", - APIKey: "your-api-key", - Timeout: 30 * time.Second, -}) -``` - -### 10.2 SDK 方法清单 - -| 方法 | 说明 | -|------|------| -| `SubmitTask(ctx, req)` | 提交任务(JSON) | -| `SubmitTaskWithFiles(ctx, req, files)` | 提交任务(带文件) | -| `GetTask(ctx, taskID)` | 获取任务详情 | -| `GetTaskStatus(ctx, taskID)` | 获取任务状态 | -| `ListTasks(ctx, status, limit, offset)` | 获取任务列表 | -| `CancelTask(ctx, taskID)` | 取消任务 | -| `GetCapabilities(ctx)` | 获取能力清单 | -| `WaitForTask(ctx, taskID, interval)` | 等待任务完成(轮询) | - -### 10.3 数据结构 - -```go -type TaskRequest struct { - TaskType string - Payload map[string]any - ExternalTaskID string - Priority string - CallbackURL string - CallbackToken string -} - -type TaskInfo struct { - ID string - Type string - Status string - Progress int - Message string - CreatedAt string - UpdatedAt string - CompletedAt string - ETA string - Result map[string]any - Error *TaskError - ExternalTaskID string -} -``` - -**完整 SDK 实现:** [sdk/client.go](../sdk/client.go) - ---- - -## 11. 参考实现 - -本协议的参考实现: - -| 模块 | 文件路径 | 说明 | -|------|---------|------| -| 服务端 | [externalapi/handler.go](../externalapi/handler.go) | External API Handler | -| 客户端 SDK | [sdk/client.go](../sdk/client.go) | Go 语言 SDK | - ---- - -## 附录 A:调用模式选择 - -### 回调模式 vs 轮询模式 - -| 对比项 | 回调模式 | 轮询模式 | -|--------|---------|---------| -| 实时性 | 高,状态变化即时通知 | 低,取决于轮询间隔 | -| 实现复杂度 | 调用方需提供公网可访问的回调接口 | 简单,只需调用 GET 接口 | -| 网络要求 | 调用方需要公网可达 | 只需调用方能访问服务端 | -| 适用场景 | 生产环境、需要实时通知 | 开发测试、内网环境 | - -### 选择建议 - -- **有公网服务器**:使用回调模式 -- **本地开发 / 内网环境**:使用轮询模式 -- **长时间任务**:建议回调模式,避免频繁轮询 -- **短任务(<10s)**:可直接同步等待或高频轮询 - ---- - -## 附录 B:从 A2A 协议到 P2A 协议的映射 - -| 灵隙概念 | P2A 对应 | 说明 | -|---------|---------|------| -| `p2p:task_request` | `POST /task` | 任务提交 | -| `p2p:task_status_update` | 回调 / GET /task | 状态更新 | -| `p2p:task_complete` | 回调(status=completed) | 任务完成 | -| `p2p:task_failed` | 回调(status=failed) | 任务失败 | -| `p2p:task_cancel` | `POST /task/{id}/cancel` | 任务取消 | -| `p2p:capability_query` | `GET /capabilities` | 能力查询 | -| Agent 身份 | API Key | 简化认证 | -| HMAC 签名 | Callback Token | 简化验证 | diff --git a/docs/05-sdk-implementation.md b/docs/05-sdk-implementation.md deleted file mode 100644 index 684a996..0000000 --- a/docs/05-sdk-implementation.md +++ /dev/null @@ -1,519 +0,0 @@ -# SDK 实现说明 - -> 版本:1.0.0 -> 更新日期:2026-06-27 -> 协议版本:1.0.0 -> 关联协议: -> - [A2A 协议](./02-a2a-protocol.md) -> - [A2N 协议](./03-a2n-protocol.md) -> - [P2A 协议](./04-p2a-protocol.md) - ---- - -## 1. 概述 - -SDK 按照灵隙协议族(Synapse Protocol Suite)的三个子协议进行了模块化设计,分为三个子包,命名与协议名保持一致: - -``` -┌─────────────────────────────────────────────────────────────┐ -│ SDK (sdk/) │ -├──────────────┬───────────────────┬───────────────────────────┤ -│ sdk/p2a │ sdk/a2a │ sdk/a2n │ -│ P2A 协议 │ A2A 协议 │ A2N 协议 │ -│ (外部调用) │ (Agent间通信) │ (群组协作) │ -│ ✅ 完整实现 │ ✅ 完整实现 │ ✅ 完整实现 │ -└──────────────┴───────────────────┴───────────────────────────┘ -``` - ---- - -## 2. SDK 目录结构 - -``` -sdk/ -├── doc.go # SDK 包文档(使用说明) -├── p2a/ -│ └── client.go # P2A 协议 - 外部调用客户端 -├── a2a/ -│ └── client.go # A2A 协议 - Agent间通信客户端 -└── a2n/ - └── client.go # A2N 协议 - 群组协作客户端 -``` - ---- - -## 3. 第一部分:sdk/p2a - P2A 协议 - -**协议对应**:[P2A 协议](./04-p2a-protocol.md) -**版本**:1.0.0 -**用途**:非 Agent 调用方(前端、后端服务、第三方应用)通过 REST API 调用 Agent 能力 - -### 3.1 实现对应关系 - -| P2A 协议功能 | SDK 方法 | 位置 | -|-------------|---------|------| -| 认证方式 | `setHeaders()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 提交任务(JSON) | `SubmitTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 提交任务(Multipart) | `SubmitTaskWithFiles()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务详情 | `GetTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务状态(简化版) | `GetTaskStatus()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务列表 | `ListTasks()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 取消任务 | `CancelTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 能力查询 | `GetCapabilities()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 回调验证 | `VerifyCallback()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 轮询等待 | `WaitForTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | - -### 3.2 核心数据结构 - -```go -// Client 客户端 -type Client struct { - baseURL string - apiKey string - httpClient *http.Client -} - -// 配置 -type ClientConfig struct { - BaseURL string - APIKey string - Timeout time.Duration - MaxRetries int -} - -// 任务请求 -type TaskRequest struct { - TaskType string - Payload map[string]any - ExternalTaskID string - Priority string - CallbackURL string - CallbackToken string -} - -// 任务信息 -type TaskInfo struct { - ID string - Type string - Status string - Progress int - Result map[string]any - Error *TaskError -} - -// 文件上传参数 -type FileParam struct { - FieldName string - Filename string - Data []byte - MimeType string -} -``` - -### 3.3 使用示例 - -```go -import "dp-headless/synapse/sdk/p2a" - -client := p2a.NewClient(p2a.ClientConfig{ - BaseURL: "https://agent-api.example.com", - APIKey: "your-api-key", -}) - -// 提交任务并等待完成 -taskInfo, err := client.CreateAndWait(ctx, "text_generation", map[string]any{ - "prompt": "写一首诗", - "style": "古典", -}, 5*time.Second) - -// 使用回调模式 -resp, err := client.CreateWithCallback(ctx, "image_generation", payload, - "https://your-domain.com/callback", - "callback-token", -) -``` - ---- - -## 4. 第二部分:sdk/a2a - A2A 协议 - -**协议对应**:[A2A 协议](./02-a2a-protocol.md) -**版本**:1.0.0 -**用途**:Agent 之间的点对点通信,包含消息发送、签名验证、回调处理 - -### 4.1 实现对应关系 - -| A2A 协议功能 | SDK 方法 | 位置 | -|------------|---------|------| -| 发送任务请求 | `SendTaskRequest()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 发送任务取消 | `SendTaskCancel()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 发送人类决策 | `SendHumanDecision()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 查询能力 | `SendCapabilityQuery()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 消息签名 | `signMessage()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 签名验证 | `verifySignature()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 任务状态管理 | `GetTaskState()`, `ListTasks()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 等待任务完成 | `WaitForTask()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 回调服务 | `startCallbackServer()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | - -### 4.2 核心数据结构 - -```go -// Client A2A客户端 -type Client struct { - agentEndpoint types.AgentEndpoint - authSecret string - callbackHandler MessageCallbackHandler - tasks map[string]*A2ATaskState -} - -// 配置 -type ClientConfig struct { - AgentEndpoint types.AgentEndpoint - AuthSecret string - CallbackPort int - Timeout time.Duration - MaxRetries int -} - -// 消息回调处理器接口 -type MessageCallbackHandler interface { - HandleTaskRequest(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) - HandleTaskStatusUpdate(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskComplete(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskFailed(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleNeedHuman(ctx context.Context, msg *types.UnifiedSynapseMessage) error -} - -// 任务状态 -type A2ATaskState struct { - TaskID string - Status types.P2PTaskStatus - Progress int - Message string - Result any - Error *types.SynapseError -} -``` - -### 4.3 使用示例 - -```go -import "dp-headless/synapse/sdk/a2a" - -a2aClient, err := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "my-agent", - AgentName: "我的Agent", - SystemID: "my-system", - Endpoint: "http://localhost:8080/synapse/callback", - }, - AuthSecret: "my-hmac-secret", - CallbackPort: 8080, -}) - -// 设置消息处理器 -a2aClient.SetMessageHandler(&myHandler{}) - -// 发送任务请求给其他Agent -taskID, err := a2aClient.SendTaskRequest(ctx, targetAgent, "video_generation", map[string]any{ - "prompt": "生成一段视频", -}) -``` - ---- - -## 5. 第三部分:sdk/a2n - A2N 协议 - -**协议对应**:[A2N 协议](./03-a2n-protocol.md) -**版本**:1.0.0 -**用途**:多 Agent 群组协作,包含群组管理、任务拆分合并、投票、升级 - -### 5.1 实现对应关系 - -| A2N 协议功能 | SDK 方法 | 位置 | -|------------|---------|------| -| 创建群组 | `CreateGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 加入群组 | `JoinGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 离开群组 | `LeaveGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 解散群组 | `DisbandGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 提交群组任务 | `SubmitGroupTask()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 发送子任务结果 | `SendSubtaskResult()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 发起投票 | `InitiateVote()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 提交投票 | `SubmitVote()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 广播消息 | `Broadcast()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 升级到人类 | `EscalateToHuman()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | - -### 5.2 核心数据结构 - -```go -// Client A2N客户端 -type Client struct { - a2aClient *a2a.Client - groups map[string]*GroupState - eventHandler GroupEventHandler -} - -// 配置 -type ClientConfig struct { - A2AClient *a2a.Client - EventHandler GroupEventHandler -} - -// 群组状态 -type GroupState struct { - GroupID string - Name string - Topology types.GroupTopology - Status types.GroupStatus - Members []types.GroupMember - Role string // "coordinator" | "worker" -} - -// 群组事件处理器接口 -type GroupEventHandler interface { - OnGroupCreated(ctx context.Context, groupID string) error - OnGroupDisbanded(ctx context.Context, groupID string) error - OnMemberJoined(ctx context.Context, groupID string, member types.GroupMember) error - OnMemberLeft(ctx context.Context, groupID string, agentID string) error - OnTaskSplit(ctx context.Context, groupID string, originalTaskID string, subtasks []types.Subtask) error - OnSubtaskProgress(ctx context.Context, groupID string, subtaskID string, progress int) error - OnTaskMerged(ctx context.Context, groupID string, originalTaskID string, result any) error - OnVoteInitiated(ctx context.Context, groupID string, vote types.GroupVotePayload) error - OnVoteResult(ctx context.Context, groupID string, voteID string, option string, passed bool) error - OnEscalation(ctx context.Context, groupID string, escalationID string, level int) error - OnBroadcast(ctx context.Context, groupID string, sender types.AgentEndpoint, message []byte) error -} -``` - -### 5.3 使用示例 - -```go -import ( - "dp-headless/synapse/sdk/a2n" - "dp-headless/synapse/sdk/a2a" -) - -// 创建A2A客户端 -a2aClient, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: myEndpoint, -}) - -// 创建A2N客户端 -a2nClient, err := a2n.NewClient(&a2n.ClientConfig{ - A2AClient: a2aClient, - EventHandler: &myGroupHandler{}, -}) - -// 创建群组 -group, err := a2nClient.CreateGroup(ctx, "视频制作组", types.GroupTopologyStar, nil, members) - -// 作为Coordinator,提交任务 -subtasks, err := a2nClient.SubmitGroupTask(ctx, group.GroupID, "video_generation", - map[string]any{"script": "..."}, - types.MergeAllSuccess, -) - -// 发起投票 -voteID, err := a2nClient.InitiateVote(ctx, group.GroupID, - "选择哪个方案?", - []string{"方案A", "方案B"}, - voterIDs, - 0.5, - 5*time.Minute, -) -``` - ---- - -## 6. SDK 架构总览 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ SDK (dp-headless/synapse/sdk) │ -├─────────────────────────────────────────────────────────────┤ -│ doc.go │ -│ ├── 包文档和使用说明 │ -│ └── 指向各子包的链接 │ -├────────────────┬────────────────┬─────────────────────────┤ -│ sdk/p2a │ sdk/a2a │ sdk/a2n │ -│ │ │ │ -│ P2A协议 │ 灵隙协议 │ A2N协议 │ -│ │ │ │ -│ ├── Client │ ├── Client │ ├── Client │ -│ ├── 配置 │ ├── 配置 │ ├── 配置 │ -│ ├── 任务操作 │ ├── 消息发送 │ ├── 群组管理 │ -│ ├── 能力查询 │ ├── 任务状态 │ ├── 任务协作 │ -│ └── 回调验证 │ ├── 回调服务 │ ├── 投票 │ -│ │ └── 签名 │ └── 升级 │ -└────────────────┴────────────────┴─────────────────────────┘ -``` - ---- - -## 7. 快速开始 - -### 7.1 P2A 调用(外部调用者) - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/p2a" -) - -func main() { - client := p2a.NewClient(p2a.ClientConfig{ - BaseURL: "https://agent.example.com", - APIKey: "your-api-key", - }) - - ctx := context.Background() - - // 方式1: 轮询等待 - result, err := client.CreateAndWait(ctx, "text_generation", map[string]any{ - "prompt": "写一首诗", - }, 5*time.Second) - if err != nil { - fmt.Println("Error:", err) - } - fmt.Printf("Result: %v\n", result.Result) - - // 方式2: 回调模式 - resp, err := client.CreateWithCallback(ctx, "image_generation", - map[string]any{"prompt": "一只猫"}, - "https://your-domain.com/callback", - "token", - ) - fmt.Printf("Task ID: %s\n", resp.TaskID) -} -``` - -### 7.2 灵隙 通信(Agent 间) - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/a2a" - "dp-headless/synapse/types" -) - -func main() { - client, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "agent-001", - AgentName: "Agent 001", - SystemID: "my-system", - Endpoint: "http://localhost:8080/synapse/callback", - }, - AuthSecret: "secret-key", - CallbackPort: 8080, - }) - - ctx := context.Background() - target := types.AgentEndpoint{ - AgentID: "agent-002", - Endpoint: "http://agent-002:8080/synapse/callback", - } - - // 发送任务请求 - taskID, err := client.SendTaskRequest(ctx, target, "data_analysis", map[string]any{ - "dataset": "sales.csv", - }) - fmt.Printf("Task ID: %s\n", taskID) - - // 等待完成 - state, err := client.WaitForTask(ctx, taskID, 5*time.Minute) - fmt.Printf("Status: %s\n", state.Status) -} -``` - -### 7.3 A2N 群组协作 - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/a2n" - "dp-headless/synapse/sdk/a2a" - "dp-headless/synapse/types" -) - -func main() { - a2aClient, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: myEndpoint, - }) - - a2nClient, _ := a2n.NewClient(&a2n.ClientConfig{ - A2AClient: a2aClient, - }) - - ctx := context.Background() - - // 创建群组 - group, _ := a2nClient.CreateGroup(ctx, "协作组", types.GroupTopologyStar, nil, []types.AgentEndpoint{ - {AgentID: "member-1", Endpoint: "http://member-1:8080"}, - {AgentID: "member-2", Endpoint: "http://member-2:8080"}, - }) - - fmt.Printf("Group ID: %s\n", group.GroupID) - - // 提交任务 - subtasks, _ := a2nClient.SubmitGroupTask(ctx, group.GroupID, "video_generation", - map[string]any{"script": "..."}, - types.MergeAllSuccess, - ) - - fmt.Printf("Split into %d subtasks\n", len(subtasks)) -} -``` - ---- - -## 8. 协议与包名对应关系 - -| 协议名称 | 协议文档 | SDK 包名 | 包路径 | -|---------|---------|---------|--------| -| 灵隙原始协议(Synapse Raw Protocol) | [01-synapse-raw-protocol.md](./01-synapse-raw-protocol.md) | - | 纲领性文档 | -| A2A 协议 | [02-a2a-protocol.md](./02-a2a-protocol.md) | `a2a` | `sdk/a2a/` | -| A2N 协议 | [03-a2n-protocol.md](./03-a2n-protocol.md) | `a2n` | `sdk/a2n/` | -| P2A 协议 | [04-p2a-protocol.md](./04-p2a-protocol.md) | `p2a` | `sdk/p2a/` | - -**所有协议版本:1.0.0** - ---- - -## 9. 扩展建议 - -| 优先级 | 扩展项 | 说明 | -|-------|-------|------| -| 高 | gRPC 传输 | 添加 gRPC 协议支持 | -| 高 | WebSocket | 添加 WebSocket 流式传输 | -| 中 | 批量操作 | 批量任务提交、批量查询 | -| 中 | 指标监控 | 内置指标收集 | -| 低 | 多语言 SDK | Python、JavaScript 等 | - ---- - -## 附录:相关文件索引 - -| 文件路径 | 说明 | -|---------|------| -| [sdk/doc.go](../sdk/doc.go) | SDK 包文档 | -| [sdk/p2a/client.go](../sdk/p2a/client.go) | P2A 客户端实现 | -| [sdk/a2a/client.go](../sdk/a2a/client.go) | A2A 客户端实现 | -| [sdk/a2n/client.go](../sdk/a2n/client.go) | A2N 客户端实现 | -| [externalapi/handler.go](../externalapi/handler.go) | P2A 协议服务端实现 | -| [p2p/protocol.go](../p2p/protocol.go) | A2A 协议核心实现 | -| [group/protocol.go](../group/protocol.go) | A2N 协议核心实现 | -| [types/types.go](../types/types.go) | 公共类型定义 | -| [transport/transport.go](../transport/transport.go) | HTTP 传输层实现 | diff --git a/docs/06-solutions-whitepaper.md b/docs/06-solutions-whitepaper.md deleted file mode 100644 index 9126b31..0000000 --- a/docs/06-solutions-whitepaper.md +++ /dev/null @@ -1,777 +0,0 @@ -# 灵隙协议族(Synapse Protocol Suite) - 解决方案白皮书 - -> 版本:1.0.0 -> 日期:2026-06-27 -> 状态:草案 -> 前置阅读:[灵隙原始协议(Synapse Raw Protocol)](./01-a2a-raw-protocol.md) - ---- - -## 目录 - -1. [概述](#1-概述) -2. [方案一:Agent 发现与广播机制](#2-方案一agent-发现与广播机制) -3. [方案二:身份认证与信任体系](#3-方案二身份认证与信任体系) -4. [方案三:协议缺失内容补全](#4-方案三协议缺失内容补全) -5. [分阶段实施路线图](#5-分阶段实施路线图) -6. [技术选型建议](#6-技术选型建议) - ---- - -## 1. 概述 - -### 1.1 背景 - -当前灵隙协议族(Synapse Protocol Suite)定义了 Agent 之间"怎么说话"(消息格式、任务流程),但缺少: - -- **怎么找到对方** — Agent 发现与广播机制 -- **怎么相信对方** — 身份认证与信任体系 -- **怎么规模化协作** — 路由、调度、激励等基础设施 - -本文档针对上述问题给出完整的解决方案。 - -### 1.2 设计原则 - -| 原则 | 说明 | -|------|------| -| **渐进式** | 从简单到复杂,每阶段都可用 | -| **可插拔** | 组件可替换,不绑定具体实现 | -| **传输无关** | 不依赖特定底层网络 | -| **安全优先** | 身份认证是基础设施,不是可选功能 | -| **向后兼容** | 不破坏现有协议,增量扩展 | - ---- - -## 2. 方案一:Agent 发现与广播机制 - -### 2.1 整体架构 - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Agent 发现与广播层 │ -├─────────────────────┬─────────────────────┬─────────────────────────┤ -│ 集中式目录服务 │ 分布式 Gossip │ 组播/广播 │ -│ (Directory) │ (Gossip) │ (Multicast) │ -│ ┌───────────────┐ │ ┌───────────────┐ │ ┌────────────────┐ │ -│ │ 注册/注销 │ │ │ 消息泛洪 │ │ │ 子网内广播 │ │ -│ │ 能力索引 │ │ │ 状态同步 │ │ │ 邻居发现 │ │ -│ │ 名字解析 │ │ │ 节点发现 │ │ │ 本地心跳 │ │ -│ └───────────────┘ │ └───────────────┘ │ └────────────────┘ │ -└─────────────────────┴─────────────────────┴─────────────────────────┘ -``` - -### 2.2 模式一:集中式目录服务(推荐首选) - -#### 2.2.1 架构说明 - -引入 **Agent Directory Service(ADS)** 作为中心化的 Agent 目录服务,类似 DNS。 - -``` -Agent A ──注册──▶ ┌─────────────┐ ◀──注册── Agent B - │ Directory │ -Agent C ──查询──▶ │ Service │ ◀──心跳── Agent D - └─────────────┘ - │ - ▼ - 能力索引 - 在线状态 - 端点地址 -``` - -#### 2.2.2 核心接口 - -**注册协议(Agent → Directory):** - -| 操作 | 消息类型 | 说明 | -|------|---------|------| -| 注册 | `dir:register` | Agent 上线时注册自身信息 | -| 注销 | `dir:unregister` | Agent 下线时注销 | -| 心跳 | `dir:heartbeat` | 定期上报存活状态 | -| 更新能力 | `dir:update_capabilities` | 能力变化时更新 | - -**查询协议(Agent → Directory):** - -| 操作 | 消息类型 | 说明 | -|------|---------|------| -| 按 ID 查询 | `dir:query_by_id` | 根据 AgentID 查端点 | -| 按能力查询 | `dir:query_by_capability` | 找具备某能力的 Agent | -| 列表查询 | `dir:list` | 分页列出所有 Agent | -| 批量查询 | `dir:batch_query` | 批量查询多个 Agent | - -#### 2.2.3 注册数据结构 - -```json -{ - "agent_id": "agent-001", - "agent_name": "视频生成Agent", - "system_id": "video-system", - "endpoint": "https://agent-001.example.com/synapse/callback", - "version": "1.0.0", - "capabilities": [ - { - "type": "video_generation", - "name": "视频生成", - "description": "根据脚本生成视频", - "max_concurrent": 10, - "avg_latency_ms": 5000 - } - ], - "transports": ["http", "grpc"], - "status": "online", - "last_heartbeat": "2026-06-27T10:00:00Z", - "trust_score": 85, - "public_key": "-----BEGIN PUBLIC KEY-----\n..." -} -``` - -#### 2.2.4 优缺点 - -| 优点 | 缺点 | -|------|------| -| 查询效率高(O(1)) | 单点故障风险 | -| 支持复杂查询(按能力、按系统等) | 中心节点需信任 | -| 易于管理和监控 | 扩展性有上限 | -| 实现简单 | 存在注册/注销时序问题 | - ---- - -### 2.3 模式二:分布式 Gossip 协议(可选扩展) - -#### 2.3.1 架构说明 - -无中心节点,Agent 之间通过 Gossip 协议(epidemic protocol)扩散状态信息,类似比特币网络的节点发现。 - -``` -Agent A ──gossip──▶ Agent B ──gossip──▶ Agent D - │ │ - └──gossip──▶ Agent C ──gossip──▶ Agent E -``` - -#### 2.3.2 核心机制 - -| 机制 | 说明 | -|------|------| -| **Peer Sampling** | 每个 Agent 维护一个部分视图(partial view) | -| **Active Push** | 定期随机选几个节点推送本地状态 | -| **Passive Pull** | 收到推送后,有概率回传自身状态 | -| **TTL** | 消息有存活跳数,防止无限扩散 | -| **Deduplication** | 消息 ID 去重,避免重复处理 | - -#### 2.3.3 Gossip 消息格式 - -```json -{ - "type": "gossip:state", - "from": "agent-001", - "view": [ - {"agent_id": "agent-002", "endpoint": "...", "capabilities": [...], "timestamp": "..."}, - {"agent_id": "agent-003", "endpoint": "...", "capabilities": [...], "timestamp": "..."}, - {"agent_id": "agent-004", "endpoint": "...", "capabilities": [...], "timestamp": "..."} - ], - "ttl": 5, - "msg_id": "msg-xxx" -} -``` - -#### 2.3.4 优缺点 - -| 优点 | 缺点 | -|------|------| -| 完全去中心化 | 查询效率低(需本地构建视图) | -| 容错性强 | 状态最终一致,有延迟 | -| 可无限扩展 | 实现复杂度高 | -| 无单点故障 | 网络流量大 | - ---- - -### 2.4 模式三:本地组播/邻居发现(局域网场景) - -适用于同一内网/集群内的 Agent 快速发现。 - -#### 2.4.1 机制 - -| 机制 | 说明 | -|------|------| -| **UDP 组播** | 定期在组播地址发送广播 | -| **mDNS/DNS-SD** | 类似 Apple Bonjour 的服务发现 | -| **ARP/NDP** | 链路层发现(不推荐) | - -#### 2.4.2 适用场景 - -- 边缘计算集群 -- 同一机房内的 Agent 集群 -- 本地开发测试环境 - ---- - -### 2.5 广播机制设计 - -#### 2.5.1 广播类型 - -| 广播范围 | 消息类型前缀 | 说明 | -|---------|-------------|------| -| 全网广播 | `global:` | 所有在线 Agent | -| 系统广播 | `system:` | 同一 system_id 内 | -| 群组广播 | `group:` | 同一群组内(已有) | -| 能力组广播 | `cap:` | 具备某能力的 Agent | - -#### 2.5.2 广播实现 - -**集中式模式下:** -- 由 Directory Service 转发广播消息 -- 支持按条件过滤(按能力、按系统等) - -**分布式模式下:** -- 通过 Gossip 协议泛洪 -- TTL 控制扩散范围 -- 消息 ID 去重 - ---- - -### 2.6 心跳与存活检测 - -#### 2.6.1 心跳机制 - -``` -Agent ───heartbeat──▶ Directory - (每30秒) - -Directory 判定离线: - - 连续 3 次未收到心跳 → 标记为 offline - - 离线 24 小时 → 自动注销 -``` - -#### 2.6.2 主动探测 - -``` -Directory ───ping──▶ Agent - ◀──pong── -``` - -用于验证 Agent 是否真的在线(防止心跳伪造)。 - ---- - -## 3. 方案二:身份认证与信任体系 - -### 3.1 三层身份架构 - -``` -┌─────────────────────────────────────────────────┐ -│ Layer 3: 信任评分 (Trust Score) │ -│ 声誉系统、历史行为、第三方评价 │ -├─────────────────────────────────────────────────┤ -│ Layer 2: 身份验证 (Authentication) │ -│ 签名验证、证书校验、DID 验证 │ -├─────────────────────────────────────────────────┤ -│ Layer 1: 身份标识 (Identity) │ -│ AgentID + 公钥 / 证书 / DID │ -└─────────────────────────────────────────────────┘ -``` - -### 3.2 Layer 1:身份标识方案 - -#### 3.2.1 方案 A:公钥身份(推荐基础版) - -**核心思想**:AgentID = 公钥哈希(类似比特币地址) - -``` -AgentID = base58(sha256(public_key)[:20]) -例:agent-1A2B3C4D5E6F... -``` - -**优点:** -- 自包含,不需要中心 CA -- 公钥可验证身份 -- 实现简单 - -**缺点:** -- 身份无法撤销(私钥泄露 = 身份被盗) -- 没有人类可读的名字 -- 无法关联真实世界身份 - -**适用场景**:内部系统、测试环境、信任度要求不高的场景 - -#### 3.2.2 方案 B:PKI 证书体系 - -**核心思想**:引入 CA(Certificate Authority)颁发证书 - -``` -CA 根证书 - ├── 系统A证书 - │ ├── Agent-001 证书 - │ └── Agent-002 证书 - └── 系统B证书 - └── Agent-003 证书 -``` - -**优点:** -- 成熟的工业标准 -- 支持证书撤销(CRL/OCSP) -- 有层级信任关系 - -**缺点:** -- 需要信任中心化 CA -- 证书管理复杂 -- 跨 CA 互操作需要桥接 - -**适用场景**:企业内部、有明确信任中心的场景 - -#### 3.2.3 方案 C:区块链 DID(去中心化身份) - -**核心思想**:身份上链,链上存公钥和属性,类似 W3C DID 标准。 - -``` -链上存储: - DID → { - "publicKey": "...", - "controller": "...", - "authentication": [...], - "service": [...], - "revoked": false, - "timestamp": "..." - } -``` - -**三种实现路径:** - -| 路径 | 说明 | 适用场景 | -|------|------|---------| -| **公链 DID** | 使用以太坊/Solana 等公链 | 开放生态、跨组织协作 | -| **联盟链 DID** | 多机构共建联盟链 | 行业联盟、政企合作 | -| **私有链 DID** | 单组织内部链 | 企业内部、对性能要求高 | - -**优点:** -- 去中心化,无单点故障 -- 身份可验证、可追溯 -- 支持跨系统互认 -- 不可篡改的身份历史 - -**缺点:** -- 链上操作有延迟 -- 需要支付 Gas 费(公链) -- 实现复杂度高 -- 隐私保护需额外设计 - ---- - -### 3.3 Layer 2:身份验证方案 - -#### 3.3.1 消息签名验证 - -所有灵隙消息必须签名,签名方式: - -``` -签名内容 = SHA256(message_id + sender + receiver + payload + timestamp) -签名 = Sign(private_key, 签名内容) -验证 = Verify(public_key, 签名内容, 签名) -``` - -#### 3.3.2 签名放置位置 - -| 位置 | 说明 | -|------|------| -| 消息体内 | `signature` 字段 | -| HTTP Header | `X-Synapse-Signature` | -| gRPC Metadata | `x-synapse-signature` | - -#### 3.3.3 防重放攻击 - -``` -每个消息有唯一 message_id + timestamp -接收方维护已处理 message_id 缓存(如最近 1 小时) -timestamp 与本地时间差超过 5 分钟 → 拒绝 -``` - ---- - -### 3.4 Layer 3:信任评分体系 - -#### 3.4.1 信任分维度 - -| 维度 | 权重 | 说明 | -|------|------|------| -| 任务完成率 | 30% | 历史任务成功 / 总任务数 | -| 任务质量 | 25% | 结果评分、返工率 | -| 响应速度 | 15% | 平均响应时间 | -| 在线稳定性 | 15% | 在线时长 / 总时长 | -| 历史信誉 | 15% | 其他 Agent 的评价 | - -#### 3.4.2 信任分计算 - -``` -trust_score = Σ(维度_i × 权重_i) - -范围:0 - 100 -等级: - 90-100 S 级 高度可信 - 75-89 A 级 可信 - 60-74 B 级 一般可信 - 40-59 C 级 谨慎使用 - 0-39 D 级 不可信 -``` - -#### 3.4.3 信任传递 - -``` -A 信任 B(评分 90) -B 信任 C(评分 85) -A 对 C 的初始信任 = 90 × 85% × 衰减因子 = 约 68 -``` - -**注意**:信任传递有衰减,防止信任污染。 - ---- - -### 3.5 区块链适用性决策树 - -``` -是否需要跨组织协作? -├── 否 → 用 PKI 或公钥身份(简单高效) -└── 是 → 是否有共同信任的中心机构? - ├── 是 → 用 PKI 体系(成熟可靠) - └── 否 → 是否需要不可篡改的审计? - ├── 是 → 考虑联盟链 DID - └── 否 → 公钥身份 + 声誉系统可能够用 -``` - ---- - -## 4. 方案三:协议缺失内容补全 - -### 4.1 第一优先级补全(核心基础设施) - -#### 4.1.1 Agent 发现协议(ADS - Agent Discovery Service) - -**新增消息类型:** - -| 消息类型 | 方向 | 说明 | -|---------|------|------| -| `dir:register` | Agent → Directory | 注册 Agent | -| `dir:unregister` | Agent → Directory | 注销 Agent | -| `dir:heartbeat` | Agent → Directory | 心跳 | -| `dir:update_capabilities` | Agent → Directory | 更新能力 | -| `dir:query_by_id` | Agent → Directory | 按 ID 查询 | -| `dir:query_by_capability` | Agent → Directory | 按能力查询 | -| `dir:list` | Agent → Directory | 列表查询 | -| `dir:query_result` | Directory → Agent | 查询结果 | - -**新增数据结构:** `AgentDirectoryEntry`, `CapabilityIndex`, `QueryFilter` - -#### 4.1.2 身份认证规范 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `auth:challenge` | 身份挑战 | -| `auth:response` | 挑战响应 | -| `auth:cert_exchange` | 证书交换 | - -**新增内容:** -- 标准签名算法列表(Ed25519, ECDSA P-256, RSA 2048) -- 消息签名格式规范 -- 防重放攻击机制 -- 身份验证流程规范 - -#### 4.1.3 心跳与存活检测 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `net:ping` | 存活探测 | -| `net:pong` | 存活响应 | -| `net:offline_notify` | 下线通知 | - -**规范内容:** -- 心跳间隔(默认 30 秒) -- 超时判定(连续 3 次未收到 → 离线) -- 离线通知机制 - -#### 4.1.4 统一错误码体系 - -**错误分类:** - -| 错误码前缀 | 类别 | 示例 | -|-----------|------|------| -| `msg_` | 消息层 | msg_invalid_format, msg_signature_invalid | -| `auth_` | 认证层 | auth_failed, auth_expired, auth_forbidden | -| `task_` | 任务层 | task_not_found, task_timeout, task_cancelled | -| `cap_` | 能力层 | cap_lacking, cap_busy, cap_not_supported | -| `group_` | 群组层 | group_not_found, group_full, group_permission_denied | -| `dir_` | 目录层 | dir_agent_not_found, dir_query_failed | -| `net_` | 网络层 | net_timeout, net_offline, net_unreachable | -| `sys_` | 系统层 | sys_internal_error, sys_not_implemented | - ---- - -### 4.2 第二优先级补全(重要功能) - -#### 4.2.1 能力匹配与任务路由 - -**功能:** -- 智能选择最合适的 Agent 执行任务 -- 支持负载均衡(按并发数、响应速度、信任分) -- 支持任务失败自动重试/转发 - -**新增消息类型:** -- `router:submit_task` - 提交给路由器自动选择执行者 -- `router:forward` - 任务转发 - -#### 4.2.2 全网广播协议 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `global:broadcast` | 全网广播 | -| `system:broadcast` | 系统内广播 | -| `cap:broadcast` | 能力组广播 | - -**规范内容:** -- 广播范围定义 -- TTL 与去重机制 -- 广播风暴防护 - -#### 4.2.3 版本协商机制 - -**功能:** -- Agent 之间协商使用的协议版本 -- 向后兼容处理 -- 能力降级策略 - -**新增消息类型:** -- `meta:version_query` - 查询支持的版本 -- `meta:version_negotiate` - 版本协商 - -#### 4.2.4 幂等性保证 - -**规范内容:** -- 幂等键(Idempotency Key)机制 -- 重复消息处理规范 -- 任务级幂等 vs 消息级幂等 - ---- - -### 4.3 第三优先级补全(增强功能) - -#### 4.3.1 流式输出协议 - -**功能:** -- 长任务实时进度推送 -- 生成式 AI 的 token 流式输出 -- WebSocket/SSE 传输支持 - -#### 4.3.2 批量任务协议 - -**功能:** -- 一次性提交多个同类型任务 -- 批量状态查询 -- 批量结果收集 - -#### 4.3.3 支付与激励机制 - -**功能:** -- 任务定价与结算 -- Token 或积分系统 -- 智能合约自动结算(区块链场景) - -#### 4.3.4 群组发现协议 - -**功能:** -- 按主题/任务类型查找群组 -- 推荐加入合适的群组 -- 群组热度/活跃度排名 - ---- - -### 4.4 安全相关补全 - -#### 4.4.1 端到端加密 - -**规范内容:** -- 密钥协商(ECDH) -- 对称加密载荷(AES-GCM) -- 前向保密(PFS) - -#### 4.4.2 权限委托 - -**功能:** -- Agent A 委托 Agent B 代表自己执行任务 -- 委托令牌(Delegation Token) -- 委托范围与时效控制 - -#### 4.4.3 审计日志标准 - -**规范内容:** -- 统一审计日志格式 -- 关键操作必须记录 -- 日志完整性保护(哈希链) - ---- - -## 5. 分阶段实施路线图 - -### 5.1 Phase 0:基础版(MVP) - 预计 2 周 - -**目标**:协议可用,能跑通基本流程 - -**内容:** -- [x] 灵隙点对点任务协议(已完成) -- [x] A2N 群组协作协议(已完成) -- [x] P2A 外部调用协议(已完成) -- [x] 三套协议的 SDK 实现(已完成) - ---- - -### 5.2 Phase 1:发现与身份 - 预计 4 周 - -**目标**:Agent 能互相找到对方,能验证对方身份 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| Agent 目录服务协议 | 集中式 ADS | P0 | -| 公钥身份规范 | Ed25519 签名验证 | P0 | -| 心跳与存活检测 | 30 秒心跳,3 次超时判定离线 | P0 | -| 统一错误码体系 | 8 大类错误码 | P0 | -| 防重放攻击 | message_id + timestamp | P0 | - -**输出物:** -- 新协议文档:`06-agent-discovery.md` -- 新协议文档:`07-authentication.md` -- 代码:`discovery/` 包(目录服务客户端) -- 代码:`auth/` 包(签名验证工具) -- 更新 types 包:新增消息类型和错误码 - ---- - -### 5.3 Phase 2:路由与广播 - 预计 4 周 - -**目标**:支持智能任务路由和全网广播 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 任务路由协议 | 按能力 + 负载 + 信任分选择执行者 | P1 | -| 全网广播协议 | 基于目录服务的广播转发 | P1 | -| 版本协商机制 | 协议版本兼容 | P1 | -| 幂等性保证 | 幂等键 + 去重 | P1 | - -**输出物:** -- 新协议文档:`08-routing-and-broadcast.md` -- 代码:`routing/` 包增强(增加能力路由) -- 更新目录服务:支持广播转发 - ---- - -### 5.4 Phase 3:信任与激励 - 预计 6 周 - -**目标**:建立信任体系,支持规模化协作 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 信任评分体系 | 5 维度信任分计算 | P2 | -| 流式输出协议 | WebSocket/SSE 流式进度 | P2 | -| 批量任务协议 | 批量提交/查询/收集 | P2 | -| 群组发现协议 | 群组搜索与推荐 | P2 | -| SLA 协议 | 服务等级承诺 | P3 | - -**输出物:** -- 新协议文档:`09-trust-and-reputation.md` -- 代码:`trust/` 包(信任评分引擎) - ---- - -### 5.5 Phase 4:高级特性 - 预计 8 周+ - -**目标**:企业级、生产级完整功能 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 端到端加密 | ECDH + AES-GCM | P3 | -| 权限委托 | 委托令牌机制 | P3 | -| 支付与激励 | Token/积分系统 | P3 | -| 区块链 DID 集成 | 可选模块 | P4 | -| 审计日志标准 | 统一审计格式 | P3 | -| Gossip 协议 | 分布式发现(可选) | P4 | - ---- - -## 6. 技术选型建议 - -### 6.1 目录服务存储选型 - -| 方案 | 适用场景 | 优点 | 缺点 | -|------|---------|------|------| -| **Redis** | 中小规模 | 高性能,支持 TTL | 数据量受限 | -| **PostgreSQL** | 中大规模 | 复杂查询,持久化 | 需运维 | -| **Elasticsearch** | 大规模 + 全文检索 | 强大的搜索能力 | 运维复杂 | - -**推荐**:先用 Redis(简单快),规模大了再迁 PostgreSQL。 - ---- - -### 6.2 签名算法选型 - -| 算法 | 安全性 | 性能 | 密钥长度 | 推荐度 | -|------|--------|------|---------|--------| -| Ed25519 | 高 | 快 | 256 位 | ⭐⭐⭐⭐⭐ 首选 | -| ECDSA P-256 | 高 | 中 | 256 位 | ⭐⭐⭐⭐ 兼容 | -| RSA 2048 | 中 | 慢 | 2048 位 | ⭐⭐ 仅兼容 | - -**推荐**:默认 Ed25519,需要兼容旧系统时支持 ECDSA。 - ---- - -### 6.3 区块链选型(如果需要) - -| 场景 | 推荐方案 | 说明 | -|------|---------|------| -| 企业内部 | **私有链(Hyperledger Fabric)** | 可控,高性能,无 Gas 费 | -| 行业联盟 | **联盟链(FISCO BCOS / ChainMaker)** | 多机构共建,合规 | -| 开放生态 | **公链(以太坊 / Solana)** | 完全开放,需 Gas 费 | -| 简单原型 | **模拟链(数据库模拟)** | 先验证逻辑,再上真链 | - -**推荐**:90% 的场景用不到真区块链,先用数据库模拟验证业务逻辑。 - ---- - -## 7. 总结与建议 - -### 7.1 核心建议 - -1. **先集中后分布**:先用集中式目录服务,简单高效;规模大了再考虑分布式 -2. **先公钥后区块链**:先用公钥身份解决 80% 的问题,真的需要了再上链 -3. **先 MVP 后完善**:先跑通核心流程,再逐步加高级功能 -4. **标准接口可替换**:目录服务、身份系统都做成可插拔的,方便未来升级 - -### 7.2 下一步行动 - -| 序号 | 行动 | 负责人 | 产出 | -|------|------|--------|------| -| 1 | 评审本方案,确认 Phase 1 范围 | 架构组 | 确认后的方案 | -| 2 | 设计目录服务 API 详细规范 | 协议组 | `06-agent-discovery.md` | -| 3 | 设计身份认证详细规范 | 协议组 | `07-authentication.md` | -| 4 | 实现目录服务原型 | 开发组 | 可运行的 ADS 服务 | -| 5 | 更新 SDK 支持发现和认证 | 开发组 | 新版 SDK | - ---- - -## 附录:相关文档索引 - -| 文档 | 说明 | -|------|------| -| [01-a2a-raw-protocol.md](./01-a2a-raw-protocol.md) | 灵隙原始协议(Synapse Raw Protocol)(纲领) | -| [02-a2a-protocol.md](./02-a2a-protocol.md) | A2A 协议(P2P 任务) | -| [03-a2n-protocol.md](./03-a2n-protocol.md) | A2N 协议(群组协作) | -| [04-p2a-protocol.md](./04-p2a-protocol.md) | P2A 协议(外部调用) | -| [05-sdk-implementation.md](./05-sdk-implementation.md) | SDK 实现说明 | -| **本文档** | **解决方案白皮书** | diff --git a/examples/group_demo.go b/examples/group_demo.go deleted file mode 100644 index e166e64..0000000 --- a/examples/group_demo.go +++ /dev/null @@ -1,414 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "net/http" - "time" - - "synapse/sdk/group" - "synapse/types" -) - -// ============================================================================= -// Group 群组测试 - 三个 Agent 之间的群组协作 -// ============================================================================= - -func main() { - fmt.Println("=== 灵隙(Synapse)Group 群组测试 ===") - fmt.Println("启动三个 Agent,进行群组协作验证...") - fmt.Println() - - // 创建群组客户端(简化版,直接在主程序模拟) - groupClient := &simpleGroupClient{ - groups: make(map[string]*group.GroupState), - } - - // 启动 Agent 1 (Coordinator) - 监听 9091 端口 - go runCoordinatorAgent(groupClient) - - // 等待 Agent 1 启动 - time.Sleep(1 * time.Second) - - // 启动 Agent 2 (Worker1) - 监听 9092 端口 - go runWorkerAgent(groupClient, "worker-1", 9092) - - // 等待 Agent 2 启动 - time.Sleep(1 * time.Second) - - // 启动 Agent 3 (Worker2) - 监听 9093 端口 - go runWorkerAgent(groupClient, "worker-2", 9093) - - // 保持主程序运行 - fmt.Println("\n=== Agent 已启动,等待群组测试 ===") - fmt.Println("Agent 1 (Coordinator): http://localhost:9091") - fmt.Println("Agent 2 (Worker-1): http://localhost:9092") - fmt.Println("Agent 3 (Worker-2): http://localhost:9093") - fmt.Println("\n按 Ctrl+C 停止...") - - // 自动创建群组并开始测试 - go func() { - time.Sleep(2 * time.Second) - createGroup() - }() - - select {} -} - -// 简化的群组客户端 -type simpleGroupClient struct { - groups map[string]*group.GroupState - members map[string][]string // groupID -> agentIDs -} - -// 创建群组并开始测试 -func createGroup() { - log.Printf("\n=== [主程序] 创建群组 ===") - - resp, err := http.Post( - "http://localhost:9091/api/group/create", - "application/json", - jsonBody(map[string]any{}), - ) - if err != nil { - log.Printf("[主程序] 创建群组失败: %v", err) - return - } - defer resp.Body.Close() - - var result map[string]any - json.NewDecoder(resp.Body).Decode(&result) - log.Printf("[主程序] 创建群组响应: %v", result) - - // 等待任务完成 - time.Sleep(8 * time.Second) -} - -type agentInfo struct { - ID string - Name string - Port int - Handler interface{} -} - -// Coordinator Agent(协调者) -func runCoordinatorAgent(client *simpleGroupClient) { - mux := http.NewServeMux() - - // 健康检查 - mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - w.Write([]byte("OK - Coordinator")) - }) - - // 群组管理 API - mux.HandleFunc("/api/group/create", func(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "method not allowed", 405) - return - } - - groupID := fmt.Sprintf("group-%d", time.Now().UnixNano()) - group := &group.GroupState{ - GroupID: groupID, - Name: "视频制作组", - Topology: types.GroupTopologyStar, - Status: types.GroupStatusActive, - Members: []types.GroupMember{ - { - AgentID: "coordinator", - AgentName: "协调者", - Role: "coordinator", - JoinedAt: types.NowTimestamp(), - Status: types.GroupMemberActive, - Capabilities: []string{"coordination"}, - LoadFactor: 0, - }, - { - AgentID: "worker-1", - AgentName: "工作者1", - Role: "worker", - JoinedAt: types.NowTimestamp(), - Status: types.GroupMemberActive, - Capabilities: []string{"video_generation"}, - LoadFactor: 0, - }, - { - AgentID: "worker-2", - AgentName: "工作者2", - Role: "worker", - JoinedAt: types.NowTimestamp(), - Status: types.GroupMemberActive, - Capabilities: []string{"audio_generation"}, - LoadFactor: 0, - }, - }, - Role: "coordinator", - } - client.groups[groupID] = group - - log.Printf("\n=== [Coordinator] 群组创建成功 ===") - log.Printf("Group ID: %s", groupID) - log.Printf("Members: coordinator, worker-1, worker-2") - - // 模拟任务拆分 - go func() { - time.Sleep(1 * time.Second) - simulateTaskSplit(groupID, client) - }() - - // 模拟投票 - go func() { - time.Sleep(3 * time.Second) - simulateVote(groupID) - }() - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]any{ - "success": true, - "group_id": groupID, - "message": "群组创建成功", - }) - }) - - // 获取群组信息 - mux.HandleFunc("/api/group/", func(w http.ResponseWriter, r *http.Request) { - groupID := r.URL.Path[len("/api/group/"):] - group, ok := client.groups[groupID] - if !ok { - http.Error(w, "group not found", 404) - return - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]any{ - "success": true, - "group": group, - }) - }) - - log.Println("[Coordinator] 协调者 Agent 启动,监听端口 9091") - if err := http.ListenAndServe(":9091", mux); err != nil { - log.Fatalf("[Coordinator] Server error: %v", err) - } -} - -// Worker Agent(工作者) -func runWorkerAgent(client *simpleGroupClient, workerID string, port int) { - mux := http.NewServeMux() - - // 健康检查 - mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - w.Write([]byte(fmt.Sprintf("OK - %s", workerID))) - }) - - // 加入群组 - mux.HandleFunc("/api/group/join", func(w http.ResponseWriter, r *http.Request) { - var req struct { - GroupID string `json:"group_id"` - } - json.NewDecoder(r.Body).Decode(&req) - - log.Printf("\n=== [%s] 申请加入群组 ===", workerID) - log.Printf("Group ID: %s", req.GroupID) - - // 模拟处理加入请求 - time.Sleep(500 * time.Millisecond) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]any{ - "success": true, - "message": fmt.Sprintf("%s 已加入群组", workerID), - "role": "worker", - "group_id": req.GroupID, - }) - }) - - // 接收任务 - mux.HandleFunc("/api/task/subtask", func(w http.ResponseWriter, r *http.Request) { - var req struct { - GroupID string `json:"group_id"` - Subtask string `json:"subtask"` - TaskType string `json:"task_type"` - Payload map[string]interface{} `json:"payload"` - } - json.NewDecoder(r.Body).Decode(&req) - - log.Printf("\n=== [%s] 收到子任务 ===", workerID) - log.Printf("Group ID: %s", req.GroupID) - log.Printf("Subtask: %s", req.Subtask) - log.Printf("Task Type: %s", req.TaskType) - log.Printf("Payload: %v", req.Payload) - - // 模拟执行任务 - go func() { - time.Sleep(1 * time.Second) - - log.Printf("[%s] 子任务执行完成: %s", workerID, req.Subtask) - - // 发送结果(这里简化处理,只是打印日志) - log.Printf("[%s] 发送子任务结果: %s -> 完成了 %s 的工作", workerID, req.Subtask, req.TaskType) - }() - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]any{ - "success": true, - "message": fmt.Sprintf("%s 开始执行任务", workerID), - "subtask": req.Subtask, - "progress": 0, - }) - }) - - // 接收投票 - mux.HandleFunc("/api/vote", func(w http.ResponseWriter, r *http.Request) { - var req struct { - GroupID string `json:"group_id"` - VoteID string `json:"vote_id"` - Question string `json:"question"` - Options []string `json:"options"` - } - json.NewDecoder(r.Body).Decode(&req) - - log.Printf("\n=== [%s] 收到投票请求 ===", workerID) - log.Printf("Vote ID: %s", req.VoteID) - log.Printf("Question: %s", req.Question) - log.Printf("Options: %v", req.Options) - - // 模拟投票决策(选择第一个选项) - selectedOption := req.Options[0] - log.Printf("[%s] 投票: %s", workerID, selectedOption) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]any{ - "success": true, - "vote_id": req.VoteID, - "selected_option": selectedOption, - "reason": "看起来更合理", - }) - }) - - log.Printf("[%s] 工作者 Agent 启动,监听端口 %d", workerID, port) - if err := http.ListenAndServe(fmt.Sprintf(":%d", port), mux); err != nil { - log.Fatalf("[%s] Server error: %v", workerID, err) - } -} - -// 模拟任务拆分 -func simulateTaskSplit(groupID string, client *simpleGroupClient) { - log.Printf("\n=== [Coordinator] 执行任务拆分 ===") - log.Printf("Original Task: 制作视频") - - subtasks := []struct { - ID string - Description string - AssignedTo string - }{ - {"sub-1", "生成视频脚本", "worker-1"}, - {"sub-2", "生成配音", "worker-2"}, - } - - for _, st := range subtasks { - log.Printf("拆分任务: %s -> %s", st.ID, st.AssignedTo) - - // 发送任务给 worker - port := 9092 - if st.AssignedTo == "worker-2" { - port = 9093 - } - - resp, err := http.Post( - fmt.Sprintf("http://localhost:%d/api/task/subtask", port), - "application/json", - jsonBody(map[string]any{ - "group_id": groupID, - "subtask": st.ID, - "task_type": "video_generation", - "payload": map[string]any{"description": st.Description}, - }), - ) - if err != nil { - log.Printf("[Coordinator] 发送任务失败: %v", err) - continue - } - resp.Body.Close() - - time.Sleep(500 * time.Millisecond) - } -} - -// 模拟投票 -func simulateVote(groupID string) { - log.Printf("\n=== [Coordinator] 发起投票 ===") - - voteQuestion := "选择视频风格?" - voteOptions := []string{"现代风格", "复古风格", "卡通风格"} - - log.Printf("Question: %s", voteQuestion) - log.Printf("Options: %v", voteOptions) - - // 收集投票结果 - votes := make(map[string]int) - for _, opt := range voteOptions { - votes[opt] = 0 - } - - // 向两个 worker 发送投票 - for _, port := range []int{9092, 9093} { - resp, err := http.Post( - fmt.Sprintf("http://localhost:%d/api/vote", port), - "application/json", - jsonBody(map[string]any{ - "group_id": groupID, - "vote_id": fmt.Sprintf("vote-%d", time.Now().UnixNano()), - "question": voteQuestion, - "options": voteOptions, - }), - ) - if err != nil { - log.Printf("[Coordinator] 投票请求失败: %v", err) - continue - } - - var result map[string]any - json.NewDecoder(resp.Body).Decode(&result) - resp.Body.Close() - - if selected, ok := result["selected_option"].(string); ok { - votes[selected]++ - } - } - - // 统计结果 - log.Printf("\n=== [Coordinator] 投票结果 ===") - for opt, count := range votes { - log.Printf("%s: %d 票", opt, count) - } - - // 确定获胜者 - var winner string - maxVotes := 0 - for opt, count := range votes { - if count > maxVotes { - maxVotes = count - winner = opt - } - } - - log.Printf("\n最终决定: %s (获得 %d 票)", winner, maxVotes) - - // 模拟结果合并 - go func() { - time.Sleep(1 * time.Second) - log.Printf("\n=== [Coordinator] 合并任务结果 ===") - log.Printf("所有子任务已完成") - log.Printf("最终结果: 视频制作完成,采用 %s", winner) - }() -} - -func jsonBody(v map[string]any) *bytes.Buffer { - data, _ := json.Marshal(v) - return bytes.NewBuffer(data) -} diff --git a/examples/p2p_demo.go b/examples/p2p_demo.go deleted file mode 100644 index aa6346e..0000000 --- a/examples/p2p_demo.go +++ /dev/null @@ -1,368 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "time" - - "synapse/sdk/p2p" - "synapse/types" -) - -// ============================================================================= -// P2P 通讯测试 - 两个 Agent 之间的点对点通信 -// ============================================================================= - -func main() { - fmt.Println("=== 灵隙(Synapse)P2P 通讯测试 ===") - fmt.Println("启动两个 Agent,进行点对点通讯验证...") - fmt.Println() - - // 启动 Agent 1 (Writer Agent) - 监听 8081 端口 - go runAgent1() - - // 等待 Agent 1 启动 - time.Sleep(1 * time.Second) - - // 启动 Agent 2 (Caller) - 监听 8082 端口 - go runAgent2() - - // 保持主程序运行 - fmt.Println("\n=== Agent 已启动,等待通讯测试 ===") - fmt.Println("Agent 1 (Writer): http://localhost:8081") - fmt.Println("Agent 2 (Caller): http://localhost:8082") - fmt.Println("\n按 Ctrl+C 停止...") - - select {} -} - -// Agent 1 - Writer Agent(任务执行方) -func runAgent1() { - // 创建 P2P 客户端 - client, err := p2p.NewClient(&p2p.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "writer-agent", - AgentName: "作家 Agent", - SystemID: "test-system", - Endpoint: "http://localhost:8081/callback", - }, - AuthSecret: "secret-123", - CallbackPort: 8081, - }) - if err != nil { - log.Fatalf("Failed to create Agent 1: %v", err) - } - - // 设置消息处理器 - client.SetMessageHandler(&writerHandler{}) - - // 启动 HTTP 服务处理回调 - mux := http.NewServeMux() - mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) { - var msg types.UnifiedSynapseMessage - if err := json.NewDecoder(r.Body).Decode(&msg); err != nil { - http.Error(w, "bad request", 400) - return - } - - resp, err := client.HandleMessage(r.Context(), &msg) - if err != nil { - log.Printf("[Agent1] Error handling message: %v", err) - http.Error(w, "internal error", 500) - return - } - - if resp != nil { - respBytes, _ := json.Marshal(resp) - w.Header().Set("Content-Type", "application/json") - w.Write(respBytes) - } - }) - - mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - w.Write([]byte("OK")) - }) - - log.Println("[Agent1] Writer Agent 启动,监听端口 8081") - if err := http.ListenAndServe(":8081", mux); err != nil { - log.Fatalf("[Agent1] Server error: %v", err) - } -} - -// Agent 2 - Caller Agent(任务请求方) -func runAgent2() { - // 创建 P2P 客户端 - client, err := p2p.NewClient(&p2p.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "caller-agent", - AgentName: "调用方 Agent", - SystemID: "test-system", - Endpoint: "http://localhost:8082/callback", - }, - AuthSecret: "secret-123", - CallbackPort: 8082, - }) - if err != nil { - log.Fatalf("Failed to create Agent 2: %v", err) - } - - // 设置消息处理器 - client.SetMessageHandler(&callerHandler{}) - - // 启动 HTTP 服务 - mux := http.NewServeMux() - mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) { - var msg types.UnifiedSynapseMessage - if err := json.NewDecoder(r.Body).Decode(&msg); err != nil { - http.Error(w, "bad request", 400) - return - } - - resp, err := client.HandleMessage(r.Context(), &msg) - if err != nil { - log.Printf("[Agent2] Error handling message: %v", err) - http.Error(w, "internal error", 500) - return - } - - if resp != nil { - respBytes, _ := json.Marshal(resp) - w.Header().Set("Content-Type", "application/json") - w.Write(respBytes) - } - }) - - mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - w.Write([]byte("OK")) - }) - - // 启动后发送测试任务 - go func() { - time.Sleep(2 * time.Second) - sendTestTask(client) - }() - - log.Println("[Agent2] Caller Agent 启动,监听端口 8082") - if err := http.ListenAndServe(":8082", mux); err != nil { - log.Fatalf("[Agent2] Server error: %v", err) - } -} - -// Writer Agent 的消息处理器 -type writerHandler struct{} - -func (h *writerHandler) HandleTaskRequest(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) { - var payload types.TaskRequestPayload - if err := json.Unmarshal(msg.Payload, &payload); err != nil { - return nil, err - } - - log.Printf("\n=== [Agent1] 收到任务请求 ===") - log.Printf("Task ID: %s", payload.Task.ID) - log.Printf("Task Type: %s", payload.Task.Type) - log.Printf("Payload: %v", payload.Task.Payload) - - // 发送任务确认 - confirmPayload, _ := json.Marshal(types.TaskConfirmPayload{ - TaskID: payload.Task.ID, - Confirmed: true, - EstimatedDuration: 5, - ExpectedCompletion: types.Timestamp(time.Now().Add(5 * time.Second).Format(time.RFC3339)), - CapabilitiesUsed: []string{"text_generation"}, - }) - - confirmMsg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PTaskConfirm), - Sender: *msg.Receiver, - Receiver: &msg.Sender, - Payload: confirmPayload, - Timestamp: types.NowTimestamp(), - } - - log.Printf("[Agent1] 发送任务确认: %s\n", payload.Task.ID) - - // 模拟处理,然后发送完成消息 - go func() { - time.Sleep(1 * time.Second) - - // 发送进度更新 - progressPayload, _ := json.Marshal(types.TaskStatusUpdatePayload{ - TaskID: payload.Task.ID, - Status: "executing", - Progress: 50, - Message: "正在生成文本...", - }) - - progressMsg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PTaskStatusUpdate), - Sender: *msg.Receiver, - Receiver: &msg.Sender, - Payload: progressPayload, - Timestamp: types.NowTimestamp(), - } - - log.Printf("[Agent1] 发送进度更新: 50%%") - _ = sendMessage(progressMsg) - - time.Sleep(1 * time.Second) - - // 发送完成消息 - result := fmt.Sprintf("生成了一个关于「%v」的故事", payload.Task.Payload["topic"]) - completePayload, _ := json.Marshal(types.TaskCompletePayload{ - TaskID: payload.Task.ID, - Result: struct { - OutputType string `json:"output_type"` - Output any `json:"output"` - Metadata map[string]interface{} `json:"metadata,omitempty"` - }{ - OutputType: "text", - Output: result, - Metadata: map[string]interface{}{"tokens": len(result)}, - }, - Summary: "任务已完成", - }) - - completeMsg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PTaskComplete), - Sender: *msg.Receiver, - Receiver: &msg.Sender, - Payload: completePayload, - Timestamp: types.NowTimestamp(), - } - - log.Printf("[Agent1] 发送任务完成: %s\n", result) - _ = sendMessage(completeMsg) - }() - - return confirmMsg, nil -} - -func (h *writerHandler) HandleTaskStatusUpdate(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - log.Printf("[Agent1] 收到状态更新: %s", msg.Type) - return nil -} - -func (h *writerHandler) HandleTaskComplete(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskCompletePayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("[Agent1] 任务完成: %s", payload.Summary) - return nil -} - -func (h *writerHandler) HandleTaskFailed(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskFailedPayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("[Agent1] 任务失败: %s", payload.Error.Message) - return nil -} - -func (h *writerHandler) HandleNeedHuman(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskNeedHumanPayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("[Agent1] 需要人类介入: %s", payload.Reason.Message) - return nil -} - -// Caller Agent 的消息处理器 -type callerHandler struct{} - -func (h *callerHandler) HandleTaskRequest(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) { - log.Printf("[Agent2] 收到任务请求") - return nil, nil -} - -func (h *callerHandler) HandleTaskStatusUpdate(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskStatusUpdatePayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("\n=== [Agent2] 收到状态更新 ===") - log.Printf("Task ID: %s", payload.TaskID) - log.Printf("Status: %s", payload.Status) - log.Printf("Progress: %d%%", payload.Progress) - log.Printf("Message: %s\n", payload.Message) - return nil -} - -func (h *callerHandler) HandleTaskComplete(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskCompletePayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("\n=== [Agent2] 收到任务完成 ===") - log.Printf("Task ID: %s", payload.TaskID) - log.Printf("Result: %v", payload.Result.Output) - log.Printf("Summary: %s\n", payload.Summary) - return nil -} - -func (h *callerHandler) HandleTaskFailed(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskFailedPayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("\n=== [Agent2] 收到任务失败 ===") - log.Printf("Task ID: %s", payload.TaskID) - log.Printf("Error: %s\n", payload.Error.Message) - return nil -} - -func (h *callerHandler) HandleNeedHuman(ctx context.Context, msg *types.UnifiedSynapseMessage) error { - var payload types.TaskNeedHumanPayload - json.Unmarshal(msg.Payload, &payload) - log.Printf("\n=== [Agent2] 收到人工介入请求 ===") - log.Printf("Task ID: %s", payload.TaskID) - log.Printf("Reason: %s\n", payload.Reason.Message) - return nil -} - -// 发送测试任务 -func sendTestTask(client *p2p.Client) { - log.Println("\n=== [Agent2] 发送测试任务 ===") - - target := types.AgentEndpoint{ - AgentID: "writer-agent", - AgentName: "作家 Agent", - SystemID: "test-system", - Endpoint: "http://localhost:8081/callback", - } - - taskID, err := client.SendTaskRequest(context.Background(), target, "text_generation", map[string]any{ - "topic": "春天", - "style": "古诗", - "length": "short", - }) - if err != nil { - log.Printf("[Agent2] 发送任务失败: %v", err) - return - } - - log.Printf("[Agent2] 任务已发送,Task ID: %s", taskID) - - // 等待任务完成 - state, err := client.WaitForTask(context.Background(), taskID, 30*time.Second) - if err != nil { - log.Printf("[Agent2] 等待任务失败: %v", err) - return - } - - log.Printf("\n=== [测试结果] ===") - log.Printf("最终状态: %s", state.Status) - log.Printf("结果: %v", state.Result) -} - -func sendMessage(msg *types.UnifiedSynapseMessage) error { - body, _ := json.Marshal(msg) - resp, err := http.Post(msg.Receiver.Endpoint, "application/json", bytes.NewReader(body)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} diff --git a/externalapi/handler.go b/externalapi/handler.go index 334b831..e0a9f94 100644 --- a/externalapi/handler.go +++ b/externalapi/handler.go @@ -79,6 +79,9 @@ func (h *ExternalAPIHandler) RegisterRoutes(mux *http.ServeMux, prefix string) { // 多部分表单提交 mux.HandleFunc(prefix+"/task/multipart", h.withAuth(h.handleTaskMultipart)) + + // 能力查询 + mux.HandleFunc(prefix+"/capabilities", h.withAuth(h.handleCapabilities)) } // ============================================================================= @@ -403,6 +406,91 @@ func (h *ExternalAPIHandler) handleTaskList(w http.ResponseWriter, r *http.Reque }) } +// ============================================================================= +// 能力查询 +// ============================================================================= + +// CapabilitiesProvider 能力提供者接口 +type CapabilitiesProvider interface { + GetCapabilities(ctx context.Context) (*CapabilitiesInfo, error) +} + +// CapabilitiesInfo 能力信息 +type CapabilitiesInfo struct { + AgentID string `json:"agent_id"` + AgentName string `json:"agent_name"` + SystemID string `json:"system_id"` + ProtocolVersion string `json:"protocol_version"` + SupportedTaskTypes []SupportedTaskType `json:"supported_task_types"` + SupportedContentTypes []string `json:"supported_content_types"` + SupportedTransportModes []string `json:"supported_transport_modes"` + MaxFileSize int64 `json:"max_file_size"` + MaxConcurrentTasks int `json:"max_concurrent_tasks"` + MaxTaskDuration int `json:"max_task_duration_seconds"` + SupportProgressUpdates bool `json:"support_progress_updates"` + SupportStreaming bool `json:"support_streaming"` + SupportHiL bool `json:"support_hil"` + SupportGroups bool `json:"support_groups"` +} + +// SupportedTaskType 支持的任务类型 +type SupportedTaskType struct { + Type string `json:"type"` + Name string `json:"name"` + Description string `json:"description"` + EstimatedTime string `json:"estimated_time"` + InputSchema string `json:"input_schema,omitempty"` + OutputSchema string `json:"output_schema,omitempty"` + Capabilities []string `json:"capabilities,omitempty"` +} + +// CapabilitiesProviderField 能力提供者字段(可选注入) +var CapabilitiesProviderField CapabilitiesProvider + +func (h *ExternalAPIHandler) handleCapabilities(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + h.writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "only GET is supported") + return + } + + // 如果有注入的能力提供者,使用它 + if CapabilitiesProviderField != nil { + caps, err := CapabilitiesProviderField.GetCapabilities(r.Context()) + if err != nil { + h.writeError(w, http.StatusInternalServerError, "capabilities_error", err.Error()) + return + } + h.writeJSON(w, http.StatusOK, map[string]any{ + "success": true, + "capabilities": caps, + }) + return + } + + // 默认能力信息 + caps := &CapabilitiesInfo{ + AgentID: "synapse-agent", + AgentName: "Synapse Agent", + SystemID: "synapse", + ProtocolVersion: "1.0.0", + SupportedTaskTypes: []SupportedTaskType{}, + SupportedContentTypes: []string{"application/json", "text/plain", "application/octet-stream"}, + SupportedTransportModes: []string{"callback", "polling"}, + MaxFileSize: h.MaxFileSize, + MaxConcurrentTasks: 10, + MaxTaskDuration: 300, + SupportProgressUpdates: true, + SupportStreaming: false, + SupportHiL: true, + SupportGroups: true, + } + + h.writeJSON(w, http.StatusOK, map[string]any{ + "success": true, + "capabilities": caps, + }) +} + // ============================================================================= // 回调发送器 // ============================================================================= diff --git a/sdk/caller/client.go b/sdk/caller/client.go deleted file mode 100644 index 8ea418d..0000000 --- a/sdk/caller/client.go +++ /dev/null @@ -1,547 +0,0 @@ -package caller - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "mime/multipart" - "net/http" - "time" -) - -// ============================================================================= -// Synapse Caller SDK (P2A Protocol) -// 非Agent调用方使用的客户端SDK -// 基于 P2A 协议:非 Agent 调用方通过 REST API 调用 Agent 能力 -// ============================================================================= - -// Client 是 Synapse P2A 服务的外部调用客户端 -type Client struct { - baseURL string - apiKey string - httpClient *http.Client -} - -// ClientConfig 客户端配置 -type ClientConfig struct { - BaseURL string - APIKey string - Timeout time.Duration - MaxRetries int -} - -// NewClient 创建新的 Synapse Caller 客户端 -func NewClient(config ClientConfig) *Client { - if config.Timeout == 0 { - config.Timeout = 30 * time.Second - } - return &Client{ - baseURL: config.BaseURL, - apiKey: config.APIKey, - httpClient: &http.Client{Timeout: config.Timeout}, - } -} - -// ============================================================================= -// 通用响应结构 -// ============================================================================= - -// APIResponse 通用 API 响应 -type APIResponse struct { - Success bool `json:"success"` - Message string `json:"message,omitempty"` - Error string `json:"error,omitempty"` -} - -// TaskResponse 任务提交响应 -type TaskResponse struct { - APIResponse - TaskID string `json:"task_id"` - Status string `json:"status"` - Message string `json:"message,omitempty"` -} - -// TaskStatusResponse 任务状态响应(简化版) -type TaskStatusResponse struct { - APIResponse - TaskID string `json:"task_id"` - Status string `json:"status"` - Progress int `json:"progress"` -} - -// TaskDetailResponse 任务详情响应 -type TaskDetailResponse struct { - APIResponse - Task TaskInfo `json:"task"` -} - -// TaskListResponse 任务列表响应 -type TaskListResponse struct { - APIResponse - Tasks []TaskInfo `json:"tasks"` - Total int `json:"total"` - Limit int `json:"limit"` - Offset int `json:"offset"` - HasMore bool `json:"has_more"` -} - -// TaskInfo 任务详情信息 -type TaskInfo struct { - ID string `json:"id"` - Type string `json:"type"` - Status string `json:"status"` - Progress int `json:"progress"` - Message string `json:"message,omitempty"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - CompletedAt string `json:"completed_at,omitempty"` - ETA string `json:"eta,omitempty"` - Result map[string]any `json:"result,omitempty"` - Error *TaskError `json:"error,omitempty"` - ExternalTaskID string `json:"external_task_id,omitempty"` -} - -// TaskError 任务错误 -type TaskError struct { - Code string `json:"code"` - Message string `json:"message"` -} - -// TaskRequest 任务请求 -type TaskRequest struct { - TaskType string `json:"task_type"` - Payload map[string]any `json:"payload"` - ExternalTaskID string `json:"external_task_id,omitempty"` - Priority string `json:"priority,omitempty"` - CallbackURL string `json:"callback_url,omitempty"` - CallbackToken string `json:"callback_token,omitempty"` -} - -// FileParam 上传文件参数 -type FileParam struct { - FieldName string - Filename string - Data []byte - MimeType string -} - -// ============================================================================= -// 能力查询 -// ============================================================================= - -// CapabilitiesResponse 能力查询响应 -type CapabilitiesResponse struct { - APIResponse - Capabilities CapabilitiesInfo `json:"capabilities"` -} - -// CapabilitiesInfo Agent 能力信息 -type CapabilitiesInfo struct { - AgentID string `json:"agent_id"` - AgentName string `json:"agent_name"` - SystemID string `json:"system_id"` - ProtocolVersion string `json:"protocol_version"` - SupportedTaskTypes []SupportedTaskType `json:"supported_task_types"` - SupportedTransportModes []string `json:"supported_transport_modes"` - MaxFileSize int64 `json:"max_file_size"` - MaxConcurrentTasks int `json:"max_concurrent_tasks"` - SupportProgressUpdates bool `json:"support_progress_updates"` - SupportStreaming bool `json:"support_streaming"` - SupportHiL bool `json:"support_hil"` - SupportGroups bool `json:"support_groups"` -} - -// SupportedTaskType 支持的任务类型 -type SupportedTaskType struct { - Type string `json:"type"` - Name string `json:"name"` - Description string `json:"description"` - EstimatedTime string `json:"estimated_time"` - InputSchema string `json:"input_schema,omitempty"` - OutputSchema string `json:"output_schema,omitempty"` -} - -// GetCapabilities 获取 Agent 能力清单 -func (c *Client) GetCapabilities(ctx context.Context) (*CapabilitiesResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/capabilities", c.baseURL) - - httpReq, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result CapabilitiesResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// ============================================================================= -// 任务提交 -// ============================================================================= - -// SubmitTask 提交任务(JSON 方式) -func (c *Client) SubmitTask(ctx context.Context, req *TaskRequest) (*TaskResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/task", c.baseURL) - - body, err := json.Marshal(req) - if err != nil { - return nil, fmt.Errorf("failed to marshal request: %w", err) - } - - httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(body)) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - httpReq.Header.Set("Content-Type", "application/json") - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// SubmitTaskWithFiles 提交带文件的任务(multipart/form-data 方式) -func (c *Client) SubmitTaskWithFiles(ctx context.Context, req *TaskRequest, files []FileParam) (*TaskResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/task/multipart", c.baseURL) - - var buf bytes.Buffer - writer := multipart.NewWriter(&buf) - - _ = writer.WriteField("task_type", req.TaskType) - - payloadJSON, _ := json.Marshal(req.Payload) - _ = writer.WriteField("payload", string(payloadJSON)) - - if req.ExternalTaskID != "" { - _ = writer.WriteField("external_task_id", req.ExternalTaskID) - } - if req.Priority != "" { - _ = writer.WriteField("priority", req.Priority) - } - if req.CallbackURL != "" { - _ = writer.WriteField("callback_url", req.CallbackURL) - } - if req.CallbackToken != "" { - _ = writer.WriteField("callback_token", req.CallbackToken) - } - - for _, f := range files { - var part io.Writer - var err error - if f.MimeType != "" { - part, err = writer.CreatePart(map[string][]string{ - "Content-Disposition": {fmt.Sprintf(`form-data; name="%s"; filename="%s"`, f.FieldName, f.Filename)}, - "Content-Type": {f.MimeType}, - }) - } else { - part, err = writer.CreateFormFile(f.FieldName, f.Filename) - } - if err != nil { - return nil, fmt.Errorf("failed to create form file: %w", err) - } - _, _ = part.Write(f.Data) - } - - _ = writer.Close() - - httpReq, err := http.NewRequestWithContext(ctx, "POST", url, &buf) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - httpReq.Header.Set("Content-Type", writer.FormDataContentType()) - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// ============================================================================= -// 任务查询 -// ============================================================================= - -// GetTask 获取任务详情 -func (c *Client) GetTask(ctx context.Context, taskID string) (*TaskDetailResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/task/%s", c.baseURL, taskID) - - httpReq, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskDetailResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// GetTaskStatus 获取任务状态(简化版) -func (c *Client) GetTaskStatus(ctx context.Context, taskID string) (*TaskStatusResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/task/%s/status", c.baseURL, taskID) - - httpReq, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskStatusResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// ListTasks 获取任务列表 -func (c *Client) ListTasks(ctx context.Context, status string, limit, offset int) (*TaskListResponse, error) { - if limit <= 0 { - limit = 20 - } - url := fmt.Sprintf("%s/api/v1/synapse/tasks?status=%s&limit=%d&offset=%d", - c.baseURL, status, limit, offset) - - httpReq, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskListResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// ============================================================================= -// 任务取消 -// ============================================================================= - -// CancelTask 取消任务 -func (c *Client) CancelTask(ctx context.Context, taskID string) (*TaskResponse, error) { - url := fmt.Sprintf("%s/api/v1/synapse/task/%s/cancel", c.baseURL, taskID) - - httpReq, err := http.NewRequestWithContext(ctx, "POST", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - c.setAuthHeaders(httpReq) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - var result TaskResponse - if err := json.Unmarshal(respBody, &result); err != nil { - return nil, fmt.Errorf("failed to decode response: %w", err) - } - - if resp.StatusCode >= 400 { - return &result, fmt.Errorf("API error: %s", result.Error) - } - - return &result, nil -} - -// ============================================================================= -// 等待任务完成 -// ============================================================================= - -// WaitForTask 等待任务完成(轮询方式) -func (c *Client) WaitForTask(ctx context.Context, taskID string, interval time.Duration) (*TaskInfo, error) { - if interval == 0 { - interval = 5 * time.Second - } - - ticker := time.NewTicker(interval) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-ticker.C: - resp, err := c.GetTask(ctx, taskID) - if err != nil { - continue - } - - switch resp.Task.Status { - case "completed", "failed", "cancelled", "rejected": - return &resp.Task, nil - } - } - } -} - -// ============================================================================= -// 回调验证 -// ============================================================================= - -// CallbackRequest 回调请求结构 -type CallbackRequest struct { - TaskID string `json:"task_id"` - Status string `json:"status"` - Progress int `json:"progress"` - Message string `json:"message,omitempty"` - Result map[string]any `json:"result,omitempty"` - Error *TaskError `json:"error,omitempty"` - Timestamp string `json:"timestamp"` -} - -// VerifyCallback 验证回调请求签名 -func (c *Client) VerifyCallback(r *http.Request, callbackToken string) bool { - if callbackToken == "" { - return true - } - token := r.Header.Get("X-Callback-Token") - return token == callbackToken -} - -// ============================================================================= -// 高阶 API: 快速创建任务并等待 -// ============================================================================= - -// CreateAndWait 创建任务并等待完成 -func (c *Client) CreateAndWait(ctx context.Context, taskType string, payload map[string]any, interval time.Duration) (*TaskInfo, error) { - req := &TaskRequest{ - TaskType: taskType, - Payload: payload, - Priority: "normal", - } - - resp, err := c.SubmitTask(ctx, req) - if err != nil { - return nil, err - } - - if !resp.Success { - return nil, fmt.Errorf("task submission failed: %s", resp.Message) - } - - return c.WaitForTask(ctx, resp.TaskID, interval) -} - -// CreateWithCallback 创建任务并指定回调 -func (c *Client) CreateWithCallback(ctx context.Context, taskType string, payload map[string]any, callbackURL, callbackToken string) (*TaskResponse, error) { - req := &TaskRequest{ - TaskType: taskType, - Payload: payload, - Priority: "normal", - CallbackURL: callbackURL, - CallbackToken: callbackToken, - } - - return c.SubmitTask(ctx, req) -} - -// ============================================================================= -// 辅助方法 -// ============================================================================= - -func (c *Client) setAuthHeaders(req *http.Request) { - if c.apiKey != "" { - req.Header.Set("X-API-Key", c.apiKey) - } - req.Header.Set("Accept", "application/json") -} diff --git a/sdk/doc.go b/sdk/doc.go index f3232bd..0b33fe6 100644 --- a/sdk/doc.go +++ b/sdk/doc.go @@ -2,9 +2,9 @@ // // 灵隙协议族(Synapse Protocol Suite)Go 语言 SDK,包含三个子包: // -// - sdk/caller: P2A 协议 - 非 Agent 调用方通过 REST API 调用 Agent 能力 -// - sdk/p2p: A2A 协议 - Agent 之间的点对点任务协作通信 -// - sdk/group: A2N 协议 - 多 Agent 群组协作(群组管理、任务拆分合并、投票) +// - sdk/p2a: P2A 协议 - 非 Agent 调用方通过 REST API 调用 Agent 能力 +// - sdk/a2a: A2A 协议 - Agent 之间的点对点任务协作通信 +// - sdk/a2n: A2N 协议 - 多 Agent 群组协作(群组管理、任务拆分合并、投票) // // 协议版本:1.0.0 package sdk diff --git a/sdk/group/client.go b/sdk/group/client.go deleted file mode 100644 index 743a412..0000000 --- a/sdk/group/client.go +++ /dev/null @@ -1,346 +0,0 @@ -package group - -import ( - "context" - "fmt" - "sync" - "time" - - "synapse/types" -) - -// ============================================================================= -// Synapse Group SDK (A2N Protocol) -// 多 Agent 群组协作客户端 SDK -// 基于 A2N 协议:多个 Agent 组成群组进行协同工作 -// ============================================================================= - -// GroupEventHandler 群组事件处理器接口 -type GroupEventHandler interface { - OnGroupCreated(ctx context.Context, groupID string) error - OnGroupDisbanded(ctx context.Context, groupID string) error - OnMemberJoined(ctx context.Context, groupID string, member types.GroupMember) error - OnMemberLeft(ctx context.Context, groupID, agentID string) error - OnTaskSplit(ctx context.Context, groupID, originalTaskID string, subtasks []types.Subtask) error - OnSubtaskProgress(ctx context.Context, groupID, subtaskID string, progress int) error - OnTaskMerged(ctx context.Context, groupID, originalTaskID string, result any) error - OnVoteInitiated(ctx context.Context, groupID string, vote types.GroupVotePayload) error - OnVoteResult(ctx context.Context, groupID, voteID, option string, passed bool) error - OnEscalation(ctx context.Context, groupID, escalationID string, level int) error - OnBroadcast(ctx context.Context, groupID string, sender types.AgentEndpoint, message []byte) error -} - -// Client A2N 群组协作客户端 -type Client struct { - p2pClient *p2pClient - groups map[string]*GroupState - groupsMu sync.RWMutex - eventHandler GroupEventHandler -} - -// p2pClient 是 P2P 客户端的简化接口 -type p2pClient interface { - SendMessage(ctx context.Context, target types.AgentEndpoint, msg *types.UnifiedSynapseMessage) error - AgentEndpoint() types.AgentEndpoint -} - -// ClientConfig A2N 客户端配置 -type ClientConfig struct { - P2PClient *p2pClient - EventHandler GroupEventHandler -} - -// GroupState 群组状态 -type GroupState struct { - GroupID string - Name string - Topology types.GroupTopology - Status types.GroupStatus - Members []types.GroupMember - Role string -} - -// NewClient 创建新的 A2N 群组客户端 -func NewClient(p2pClient interface{}, eventHandler GroupEventHandler) (*Client, error) { - return &Client{ - groups: make(map[string]*GroupState), - eventHandler: eventHandler, - }, nil -} - -// SetEventHandler 设置群组事件处理器 -func (c *Client) SetEventHandler(handler GroupEventHandler) { - c.eventHandler = handler -} - -// ============================================================================= -// 群组管理 -// ============================================================================= - -// CreateGroup 创建群组 -func (c *Client) CreateGroup(ctx context.Context, name string, topology types.GroupTopology, config *types.GroupConfig, initialMembers []types.AgentEndpoint) (*GroupState, error) { - groupID := fmt.Sprintf("group-%d", time.Now().UnixNano()) - - if config == nil { - config = &types.GroupConfig{ - AllowSelfLeave: true, - RequiresApproval: false, - ConsensusRequired: false, - ConsensusThreshold: 0.5, - BroadcastMode: "all", - } - } - - members := make([]types.GroupMember, 0, len(initialMembers)+1) - for _, m := range initialMembers { - members = append(members, types.GroupMember{ - AgentID: m.AgentID, - AgentName: m.AgentName, - Role: "worker", - JoinedAt: types.NowTimestamp(), - Status: types.GroupMemberActive, - Capabilities: []string{}, - LoadFactor: 0, - }) - } - - groupState := &GroupState{ - GroupID: groupID, - Name: name, - Topology: topology, - Status: types.GroupStatusActive, - Members: members, - Role: "coordinator", - } - - c.groupsMu.Lock() - c.groups[groupID] = groupState - c.groupsMu.Unlock() - - if c.eventHandler != nil { - _ = c.eventHandler.OnGroupCreated(ctx, groupID) - } - - return groupState, nil -} - -// JoinGroup 加入群组 -func (c *Client) JoinGroup(ctx context.Context, groupID string) error { - c.groupsMu.Lock() - defer c.groupsMu.Unlock() - - if _, ok := c.groups[groupID]; !ok { - c.groups[groupID] = &GroupState{ - GroupID: groupID, - Status: types.GroupStatusActive, - Role: "worker", - } - } - - if c.eventHandler != nil { - _ = c.eventHandler.OnMemberJoined(ctx, groupID, types.GroupMember{}) - } - - return nil -} - -// LeaveGroup 离开群组 -func (c *Client) LeaveGroup(ctx context.Context, groupID string) error { - c.groupsMu.Lock() - delete(c.groups, groupID) - c.groupsMu.Unlock() - - if c.eventHandler != nil { - _ = c.eventHandler.OnMemberLeft(ctx, groupID, "") - } - - return nil -} - -// DisbandGroup 解散群组 -func (c *Client) DisbandGroup(ctx context.Context, groupID string) error { - c.groupsMu.Lock() - if group, ok := c.groups[groupID]; ok { - group.Status = types.GroupStatusDisbanded - } - c.groupsMu.Unlock() - - if c.eventHandler != nil { - _ = c.eventHandler.OnGroupDisbanded(ctx, groupID) - } - - return nil -} - -// GetGroup 获取群组信息 -func (c *Client) GetGroup(groupID string) (*GroupState, bool) { - c.groupsMu.RLock() - defer c.groupsMu.RUnlock() - group, ok := c.groups[groupID] - return group, ok -} - -// ListGroups 列出所有群组 -func (c *Client) ListGroups() []*GroupState { - c.groupsMu.RLock() - defer c.groupsMu.RUnlock() - result := make([]*GroupState, 0, len(c.groups)) - for _, g := range c.groups { - result = append(result, g) - } - return result -} - -// ============================================================================= -// 任务协作 -// ============================================================================= - -// SubmitGroupTask 提交群组任务(作为 coordinator 拆分任务) -func (c *Client) SubmitGroupTask(ctx context.Context, groupID, taskType string, requirements map[string]any, mergeStrategy types.MergeStrategy) ([]types.Subtask, error) { - subtasks := []types.Subtask{ - { - ID: fmt.Sprintf("sub-%d-1", time.Now().UnixNano()), - Description: "子任务 1", - AssignedTo: "", - Dependencies: []string{}, - EstimatedDuration: 60, - Priority: 1, - }, - } - - if c.eventHandler != nil { - _ = c.eventHandler.OnTaskSplit(ctx, groupID, "", subtasks) - } - - return subtasks, nil -} - -// SendSubtaskResult 发送子任务结果 -func (c *Client) SendSubtaskResult(ctx context.Context, groupID, subtaskID string, result any, err error) error { - if c.eventHandler != nil { - _ = c.eventHandler.OnTaskMerged(ctx, groupID, "", result) - } - return nil -} - -// ============================================================================= -// 投票与共识 -// ============================================================================= - -// InitiateVote 发起投票 -func (c *Client) InitiateVote(ctx context.Context, groupID, question string, options []string, voterIDs []string, threshold float64, deadline time.Duration) (string, error) { - voteID := fmt.Sprintf("vote-%d", time.Now().UnixNano()) - - vote := types.GroupVotePayload{ - VoteID: voteID, - Question: question, - Options: options, - Voters: voterIDs, - Deadline: types.Timestamp(time.Now().Add(deadline).UTC().Format(time.RFC3339)), - Threshold: threshold, - Status: "open", - } - - if c.eventHandler != nil { - _ = c.eventHandler.OnVoteInitiated(ctx, groupID, vote) - } - - return voteID, nil -} - -// SubmitVote 提交投票 -func (c *Client) SubmitVote(ctx context.Context, groupID, voteID, option, reason string) error { - if c.eventHandler != nil { - _ = c.eventHandler.OnVoteResult(ctx, groupID, voteID, option, true) - } - return nil -} - -// ============================================================================= -// 广播与升级 -// ============================================================================= - -// Broadcast 广播消息 -func (c *Client) Broadcast(ctx context.Context, groupID string, message []byte) error { - if c.eventHandler != nil { - _ = c.eventHandler.OnBroadcast(ctx, groupID, types.AgentEndpoint{}, message) - } - return nil -} - -// EscalateToHuman 升级到人类决策 -func (c *Client) EscalateToHuman(ctx context.Context, groupID string, level int, reason string) (string, error) { - escalationID := fmt.Sprintf("esc-%d", time.Now().UnixNano()) - - if c.eventHandler != nil { - _ = c.eventHandler.OnEscalation(ctx, groupID, escalationID, level) - } - - return escalationID, nil -} - -// ============================================================================= -// 消息处理 -// ============================================================================= - -// HandleMessage 处理群组消息 -func (c *Client) HandleMessage(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) { - groupID := msg.GroupID - - switch types.GroupMessageType(msg.Type) { - case types.GroupCreate: - if c.eventHandler != nil { - _ = c.eventHandler.OnGroupCreated(ctx, groupID) - } - - case types.GroupDisband: - if c.eventHandler != nil { - _ = c.eventHandler.OnGroupDisbanded(ctx, groupID) - } - - case types.GroupMemberUpdate: - if c.eventHandler != nil { - _ = c.eventHandler.OnMemberJoined(ctx, groupID, types.GroupMember{}) - } - - case types.GroupTaskSplit: - var payload types.GroupTaskSplitPayload - if c.eventHandler != nil { - _ = c.eventHandler.OnTaskSplit(ctx, groupID, payload.OriginalTask.ID, payload.Subtasks) - } - - case types.GroupTaskProgress: - if c.eventHandler != nil { - _ = c.eventHandler.OnSubtaskProgress(ctx, groupID, "", 0) - } - - case types.GroupTaskMerge: - var payload types.GroupTaskMergePayload - if c.eventHandler != nil { - _ = c.eventHandler.OnTaskMerged(ctx, groupID, payload.OriginalTaskID, payload.MergedResult) - } - - case types.GroupVote: - var payload types.GroupVotePayload - if c.eventHandler != nil { - _ = c.eventHandler.OnVoteInitiated(ctx, groupID, payload) - } - - case types.GroupConsensus: - if c.eventHandler != nil { - _ = c.eventHandler.OnVoteResult(ctx, groupID, "", "", true) - } - - case types.GroupConsensusEscalate, types.GroupSubtaskEscalate: - if c.eventHandler != nil { - _ = c.eventHandler.OnEscalation(ctx, groupID, "", 1) - } - - case types.GroupBroadcast: - if c.eventHandler != nil { - _ = c.eventHandler.OnBroadcast(ctx, groupID, msg.Sender, msg.Payload) - } - } - - return nil, nil -} diff --git a/sdk/p2p/client.go b/sdk/p2p/client.go deleted file mode 100644 index aae3c2e..0000000 --- a/sdk/p2p/client.go +++ /dev/null @@ -1,459 +0,0 @@ -package p2p - -import ( - "bytes" - "context" - "crypto/hmac" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net/http" - "sync" - "time" - - "synapse/types" -) - -// ============================================================================= -// Synapse P2P SDK (A2A Protocol) -// Agent 间点对点通信客户端 SDK -// 基于 A2A 协议:两个 Agent 之间进行点对点任务协作 -// ============================================================================= - -// MessageCallbackHandler 消息回调处理器接口 -type MessageCallbackHandler interface { - HandleTaskRequest(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) - HandleTaskStatusUpdate(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskComplete(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskFailed(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleNeedHuman(ctx context.Context, msg *types.UnifiedSynapseMessage) error -} - -// Client A2A 点对点通信客户端 -type Client struct { - agentEndpoint types.AgentEndpoint - authSecret string - callbackHandler MessageCallbackHandler - tasks map[string]*P2PTaskState - tasksMu sync.RWMutex - httpClient *http.Client -} - -// ClientConfig A2A 客户端配置 -type ClientConfig struct { - AgentEndpoint types.AgentEndpoint - AuthSecret string - CallbackPort int - Timeout time.Duration - MaxRetries int -} - -// P2PTaskState P2P 任务状态 -type P2PTaskState struct { - TaskID string - Status types.P2PTaskStatus - Progress int - Message string - Result any - Error *types.SynapseError -} - -// NewClient 创建新的 A2A 客户端 -func NewClient(config *ClientConfig) (*Client, error) { - if config.Timeout == 0 { - config.Timeout = 30 * time.Second - } - - return &Client{ - agentEndpoint: config.AgentEndpoint, - authSecret: config.AuthSecret, - tasks: make(map[string]*P2PTaskState), - httpClient: &http.Client{Timeout: config.Timeout}, - }, nil -} - -// SetMessageHandler 设置消息回调处理器 -func (c *Client) SetMessageHandler(handler MessageCallbackHandler) { - c.callbackHandler = handler -} - -// ============================================================================= -// 任务状态管理 -// ============================================================================= - -// GetTaskState 获取任务状态 -func (c *Client) GetTaskState(taskID string) (*P2PTaskState, bool) { - c.tasksMu.RLock() - defer c.tasksMu.RUnlock() - state, ok := c.tasks[taskID] - return state, ok -} - -// ListTasks 列出所有任务 -func (c *Client) ListTasks() map[string]*P2PTaskState { - c.tasksMu.RLock() - defer c.tasksMu.RUnlock() - result := make(map[string]*P2PTaskState, len(c.tasks)) - for k, v := range c.tasks { - result[k] = v - } - return result -} - -func (c *Client) setTaskState(taskID string, status types.P2PTaskStatus, progress int, message string) { - c.tasksMu.Lock() - defer c.tasksMu.Unlock() - if _, ok := c.tasks[taskID]; !ok { - c.tasks[taskID] = &P2PTaskState{TaskID: taskID} - } - c.tasks[taskID].Status = status - c.tasks[taskID].Progress = progress - c.tasks[taskID].Message = message -} - -func (c *Client) setTaskResult(taskID string, result any) { - c.tasksMu.Lock() - defer c.tasksMu.Unlock() - if state, ok := c.tasks[taskID]; ok { - state.Result = result - } -} - -func (c *Client) setTaskError(taskID string, err *types.SynapseError) { - c.tasksMu.Lock() - defer c.tasksMu.Unlock() - if state, ok := c.tasks[taskID]; ok { - state.Error = err - } -} - -// ============================================================================= -// 消息发送 -// ============================================================================= - -// SendTaskRequest 发送任务请求 -func (c *Client) SendTaskRequest(ctx context.Context, target types.AgentEndpoint, taskType string, payload map[string]any) (string, error) { - taskID := types.GenerateTaskID() - - taskReq := types.TaskRequestPayload{} - taskReq.Task.ID = taskID - taskReq.Task.Type = taskType - taskReq.Task.Priority = types.PriorityNormal - taskReq.Task.Payload = payload - - payloadBytes, _ := json.Marshal(taskReq) - - msg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PTaskRequest), - Sender: c.agentEndpoint, - Receiver: &target, - Payload: payloadBytes, - Priority: types.PriorityNormal, - Timestamp: types.NowTimestamp(), - } - - c.setTaskState(taskID, types.P2PStatusPending, 0, "任务已发送") - - err := c.sendMessage(ctx, target.Endpoint, msg) - if err != nil { - return "", fmt.Errorf("failed to send task request: %w", err) - } - - return taskID, nil -} - -// SendTaskCancel 发送任务取消 -func (c *Client) SendTaskCancel(ctx context.Context, target types.AgentEndpoint, taskID, reason string) error { - cancelPayload := types.TaskCancelPayload{ - TaskID: taskID, - Reason: reason, - CancelledBy: c.agentEndpoint.AgentID, - } - - payloadBytes, _ := json.Marshal(cancelPayload) - - msg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PTaskCancel), - Sender: c.agentEndpoint, - Receiver: &target, - Payload: payloadBytes, - Timestamp: types.NowTimestamp(), - } - - c.setTaskState(taskID, types.P2PStatusCancelled, 0, "任务已取消") - - return c.sendMessage(ctx, target.Endpoint, msg) -} - -// SendHumanDecision 发送人类决策结果 -func (c *Client) SendHumanDecision(ctx context.Context, target types.AgentEndpoint, taskID string, decision types.HumanDecisionPayload) error { - payloadBytes, _ := json.Marshal(decision) - - msg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PHumanDecision), - Sender: c.agentEndpoint, - Receiver: &target, - Payload: payloadBytes, - Timestamp: types.NowTimestamp(), - } - - return c.sendMessage(ctx, target.Endpoint, msg) -} - -// SendCapabilityQuery 查询对方能力 -func (c *Client) SendCapabilityQuery(ctx context.Context, target types.AgentEndpoint) ([]string, error) { - msg := &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: "1.0.0", - Type: string(types.P2PCapabilityQuery), - Sender: c.agentEndpoint, - Receiver: &target, - Payload: []byte("{}"), - Timestamp: types.NowTimestamp(), - } - - respMsg, err := c.sendRequest(ctx, target.Endpoint, msg) - if err != nil { - return nil, fmt.Errorf("failed to query capabilities: %w", err) - } - - var resp struct { - Capabilities []string `json:"capabilities"` - } - if err := json.Unmarshal(respMsg.Payload, &resp); err != nil { - return nil, fmt.Errorf("failed to parse capabilities: %w", err) - } - - return resp.Capabilities, nil -} - -// ============================================================================= -// 消息签名与验证 -// ============================================================================= - -func (c *Client) signMessage(msg *types.UnifiedSynapseMessage) string { - if c.authSecret == "" { - return "" - } - - h := hmac.New(sha256.New, []byte(c.authSecret)) - h.Write([]byte(msg.ID + "." + string(msg.Payload))) - return hex.EncodeToString(h.Sum(nil)) -} - -// VerifySignature 验证消息签名 -func (c *Client) VerifySignature(msg *types.UnifiedSynapseMessage, secret string) bool { - if secret == "" { - return true - } - if msg.Signature == "" { - return false - } - - h := hmac.New(sha256.New, []byte(secret)) - h.Write([]byte(msg.ID + "." + string(msg.Payload))) - expected := hex.EncodeToString(h.Sum(nil)) - return hmac.Equal([]byte(msg.Signature), []byte(expected)) -} - -// ============================================================================= -// 消息发送底层 -// ============================================================================= - -func (c *Client) sendMessage(ctx context.Context, endpoint string, msg *types.UnifiedSynapseMessage) error { - msg.Signature = c.signMessage(msg) - - body, err := json.Marshal(msg) - if err != nil { - return fmt.Errorf("failed to marshal message: %w", err) - } - - httpReq, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewReader(body)) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - - httpReq.Header.Set("Content-Type", "application/json") - httpReq.Header.Set("X-Synapse-Signature", msg.Signature) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode >= 400 { - respBody, _ := io.ReadAll(resp.Body) - return fmt.Errorf("remote error: %s", string(respBody)) - } - - return nil -} - -func (c *Client) sendRequest(ctx context.Context, endpoint string, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) { - msg.Signature = c.signMessage(msg) - - body, err := json.Marshal(msg) - if err != nil { - return nil, fmt.Errorf("failed to marshal message: %w", err) - } - - httpReq, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewReader(body)) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - httpReq.Header.Set("Content-Type", "application/json") - httpReq.Header.Set("X-Synapse-Signature", msg.Signature) - - resp, err := c.httpClient.Do(httpReq) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) - } - defer resp.Body.Close() - - respBody, _ := io.ReadAll(resp.Body) - - if resp.StatusCode >= 400 { - return nil, fmt.Errorf("remote error: %s", string(respBody)) - } - - var respMsg types.UnifiedSynapseMessage - if err := json.Unmarshal(respBody, &respMsg); err != nil { - return nil, fmt.Errorf("failed to parse response: %w", err) - } - - return &respMsg, nil -} - -// ============================================================================= -// 等待任务完成 -// ============================================================================= - -// WaitForTask 等待任务完成(轮询方式,通过回调更新状态) -func (c *Client) WaitForTask(ctx context.Context, taskID string, timeout time.Duration) (*P2PTaskState, error) { - deadline := time.Now().Add(timeout) - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-ticker.C: - if time.Now().After(deadline) { - return nil, fmt.Errorf("task timeout") - } - - state, ok := c.GetTaskState(taskID) - if !ok { - continue - } - - switch state.Status { - case types.P2PStatusCompleted, types.P2PStatusFailed, types.P2PStatusCancelled, types.P2PStatusRejected: - return state, nil - } - } - } -} - -// ============================================================================= -// 回调处理 -// ============================================================================= - -// HandleMessage 处理收到的消息(供 HTTP 服务调用) -func (c *Client) HandleMessage(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) { - if c.authSecret != "" && !c.VerifySignature(msg, c.authSecret) { - return nil, fmt.Errorf("invalid signature") - } - - switch types.P2PMessageType(msg.Type) { - case types.P2PTaskRequest: - if c.callbackHandler != nil { - return c.callbackHandler.HandleTaskRequest(ctx, msg) - } - return c.ackMessage(msg), nil - - case types.P2PTaskConfirm: - var payload types.TaskConfirmPayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PStatusConfirmed, 0, "任务已确认") - return c.ackMessage(msg), nil - - case types.P2PTaskReject: - var payload types.TaskRejectPayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PStatusRejected, 0, payload.Reason.Message) - return c.ackMessage(msg), nil - - case types.P2PTaskStatusUpdate: - var payload types.TaskStatusUpdatePayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PTaskStatus(payload.Status), payload.Progress, payload.Message) - if c.callbackHandler != nil { - _ = c.callbackHandler.HandleTaskStatusUpdate(ctx, msg) - } - return c.ackMessage(msg), nil - - case types.P2PTaskComplete: - var payload types.TaskCompletePayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PStatusCompleted, 100, payload.Summary) - c.setTaskResult(payload.TaskID, payload.Result.Output) - if c.callbackHandler != nil { - _ = c.callbackHandler.HandleTaskComplete(ctx, msg) - } - return c.ackMessage(msg), nil - - case types.P2PTaskFailed: - var payload types.TaskFailedPayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PStatusFailed, 0, payload.Error.Message) - c.setTaskError(payload.TaskID, types.NewSynapseError( - types.SynapseErrorCode(0), - payload.Error.Message, - nil, - )) - if c.callbackHandler != nil { - _ = c.callbackHandler.HandleTaskFailed(ctx, msg) - } - return c.ackMessage(msg), nil - - case types.P2PTaskNeedHuman: - var payload types.TaskNeedHumanPayload - _ = json.Unmarshal(msg.Payload, &payload) - c.setTaskState(payload.TaskID, types.P2PStatusNeedHuman, 0, payload.Reason.Message) - if c.callbackHandler != nil { - _ = c.callbackHandler.HandleNeedHuman(ctx, msg) - } - return c.ackMessage(msg), nil - - case types.P2PCapabilityQuery: - return nil, nil - - default: - return c.ackMessage(msg), nil - } -} - -func (c *Client) ackMessage(msg *types.UnifiedSynapseMessage) *types.UnifiedSynapseMessage { - return &types.UnifiedSynapseMessage{ - ID: types.GenerateMessageID(), - Version: msg.Version, - Type: string(types.P2PAck), - Sender: c.agentEndpoint, - Receiver: &msg.Sender, - ReplyTo: msg.ID, - Payload: []byte("{}"), - Timestamp: types.NowTimestamp(), - } -} diff --git a/synapse/docs/01-synapse-raw-protocol.md b/synapse/docs/01-synapse-raw-protocol.md deleted file mode 100644 index baff41d..0000000 --- a/synapse/docs/01-synapse-raw-protocol.md +++ /dev/null @@ -1,328 +0,0 @@ -# 灵隙原始协议(Synapse Raw Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:纲领性文档 - ---- - -## 1. 协议愿景 - -灵隙(Synapse,原 Agent-to-Agent)协议旨在定义一套通用的、可扩展的智能体间通信标准,使不同系统、不同厂商、不同能力的智能体能够在统一的协议框架下进行协作、交易与能力组合。 - -本协议是灵隙协议族(Synapse Protocol Suite)的原始纲领,定义核心设计理念、架构原则与术语体系,为所有衍生协议提供顶层指导。 - ---- - -## 2. 核心设计理念 - -### 2.1 去中心化对等(Peer-to-Peer) -- 所有 Agent 在协议层面地位平等,无中心化控制节点 -- 每个 Agent 既是服务提供者,也是服务消费者 -- Agent 间直接通信,不依赖中间 broker(传输层可选择不同实现) - -### 2.2 能力驱动(Capability-Driven) -- 通信以能力为核心,而非以身份为核心 -- Agent 声明自身能力,按需发现与调用 -- 能力可组合、可分解、可升级 - -### 2.3 任务导向(Task-Oriented) -- 所有交互围绕"任务"展开 -- 任务有明确的生命周期、状态机与超时机制 -- 任务支持拆分、合并、委派与协作 - -### 2.4 人类可介入(Human-in-the-Loop) -- 协议原生支持人类介入决策 -- Agent 可主动请求人类判断 -- 人类决策优先于 Agent 自动决策 -- 支持多级升级(escalation)机制 - -### 2.5 群组协作(Group Collaboration) -- 支持多 Agent 组成临时或永久群组 -- 群组内有角色分工与权限控制 -- 支持任务拆分-执行-合并的 MapReduce 模式 -- 支持投票、共识等群体决策机制 - -### 2.6 传输无关(Transport Agnostic) -- 协议语义与底层传输分离 -- 支持 HTTP/2、gRPC、WebSocket、消息队列等多种传输 -- 支持回调(Callback)、轮询(Polling)、同步(Sync)、混合(Hybrid)等多种交互模式 - -### 2.7 安全可信(Secure & Trustworthy) -- 消息级签名与验证 -- Agent 身份认证与信任等级 -- 支持加密传输 -- 可审计、可追溯 - ---- - -## 3. 协议分层架构 - -``` -┌─────────────────────────────────────────┐ -│ 应用层 (Application) │ -│ 业务逻辑、工作流、领域特定逻辑 │ -├─────────────────────────────────────────┤ -│ 协议层 (Protocol) │ -├─────────────┬───────────────────────────┤ -│ A2A 协议 │ A2N 组群协议 │ ← 本协议族 -│ (P2P) │ (Group) │ -├─────────────┴───────────────────────────┤ -│ 传输层 (Transport) │ -│ HTTP / gRPC / WebSocket / MQ ... │ -├─────────────────────────────────────────┤ -│ 网络层 (Network) │ -│ TCP / UDP / QUIC ... │ -└─────────────────────────────────────────┘ -``` - -### 3.1 协议族构成 - -| 协议名称 | 缩写 | 描述 | 适用场景 | -|---------|------|------|---------| -| 灵隙原始协议(Synapse Raw Protocol) | A2A-Raw | 顶层纲领,定义理念、术语、原则 | 指导所有协议设计 | -| A2A 协议 | A2A-Base | 点对点任务协作协议 | 两个 Agent 间的任务交互 | -| A2N 组群协议 | A2N-Group | 多 Agent 群组协作协议 | 多个 Agent 协同完成任务 | -| P2A 调用协议 | P2A-Caller | 非 Agent 调用者接入协议 | 普通服务/前端调用 Agent 能力 | - ---- - -## 4. 核心概念与术语 - -### 4.1 Agent(智能体) -能够自主感知环境、做出决策并执行动作的计算实体。 - -**属性:** -- `agent_id`:Agent 唯一标识 -- `system_id`:所属系统标识 -- `endpoint`:通信端点地址 -- `capabilities`:能力清单 -- `trust_level`:信任等级 - -### 4.2 Task(任务) -Agent 间协作的基本单位,具有明确的输入、输出与生命周期。 - -**属性:** -- `task_id`:任务唯一标识 -- `task_type`:任务类型 -- `payload`:任务载荷 -- `status`:任务状态 -- `priority`:优先级 -- `deadline`:截止时间 - -### 4.3 Message(消息) -Agent 间通信的基本单位。 - -**属性:** -- `message_id`:消息唯一标识 -- `type`:消息类型 -- `sender`:发送方 -- `receiver`:接收方(P2P) -- `group_id`:群组标识(群组) -- `payload`:消息载荷 -- `correlation_id`:关联标识(用于请求-响应关联) -- `timestamp`:时间戳 -- `signature`:签名 - -### 4.4 Capability(能力) -Agent 能够执行的任务类型的声明。 - -**属性:** -- `type`:能力对应的任务类型 -- `name`:能力名称 -- `description`:能力描述 -- `input_schema`:输入参数 schema -- `output_schema`:输出结果 schema -- `estimated_time`:预估耗时 - -### 4.5 Group(群组) -由多个 Agent 组成的协作单元。 - -**属性:** -- `group_id`:群组唯一标识 -- `name`:群组名称 -- `topology`:拓扑结构 -- `members`:成员列表 -- `roles`:角色定义 -- `status`:群组状态 - -### 4.6 Human-in-the-Loop(人在回路) -在 Agent 协作过程中,人类可介入进行决策的机制。 - -**关键概念:** -- `escalation`:升级(将问题提交给人类) -- `decision`:决策(人类做出的判断) -- `resume`:恢复(人类决策后继续执行) - ---- - -## 5. 设计原则 - -### 5.1 简约性(Simplicity) -- 核心机制保持简单 -- 复杂功能通过组合基础机制实现 -- 可选功能通过能力声明来协商 - -### 5.2 可扩展性(Extensibility) -- 消息类型可扩展 -- 能力类型可扩展 -- 传输方式可扩展 -- 通过版本号与能力协商保证向后兼容 - -### 5.3 容错性(Fault Tolerance) -- 网络不可靠是常态 -- 消息可能丢失、重复、延迟 -- Agent 可能故障、离线 -- 协议必须有重试、超时、降级机制 - -### 5.4 可观测性(Observability) -- 所有交互可追踪 -- 任务状态可查询 -- 支持日志、指标、链路追踪 - -### 5.5 互操作性(Interoperability) -- 不同语言、不同框架的 Agent 可互操作 -- 协议规范优先于具体实现 -- 提供标准测试用例验证兼容性 - ---- - -## 6. 消息模型总则 - -### 6.1 统一消息信封 -所有协议共享统一的消息信封结构,具体载荷由消息类型决定。 - -``` -UnifiedSynapseMessage -├── id // 消息ID -├── version // 协议版本 -├── type // 消息类型 -├── sender // 发送方 AgentEndpoint -├── receiver? // 接收方(P2P 时) -├── group_id? // 群组ID(群组时) -├── correlation_id // 关联ID -├── reply_to? // 回复的消息ID -├── payload // 消息载荷(JSON) -├── priority? // 优先级 -├── signature? // 签名 -├── timestamp // 发送时间 -└── expires_at? // 过期时间 -``` - -### 6.2 消息命名规范 -- 使用 `领域:动作` 格式 -- 全小写,用下划线分隔 -- 示例:`p2p:task_request`, `group:create`, `hil:decision` - -### 6.3 请求-响应模式 -- 请求消息必须携带唯一 `id` -- 响应消息通过 `reply_to` 关联请求 -- 支持 ACK/NACK 机制 -- 超时未收到响应应重试或报错 - ---- - -## 7. 任务生命周期总则 - -### 7.1 状态机 - -``` - ┌──────────┐ - │ pending │ 待确认 - └────┬─────┘ - │ 确认/拒绝 - ┌─────┴──────┐ - ▼ ▼ - ┌─────────┐ ┌──────────┐ - │confirmed│ │ rejected │ 已拒绝(终态) - └────┬────┘ └──────────┘ - │ 开始执行 - ▼ - ┌──────────┐ - │executing │ 执行中 - └────┬─────┘ - │ 信息缺失 - ┌────▼─────┐ - │info_needed│ 需要信息 - └────┬─────┘ - │ 信息补充 - ▼ - 回到 executing - │ - ├──────────────┐ - │ 需人类决策 │ - ▼ ▼ - ┌──────────┐ ┌───────────┐ - │need_human│ │ 各种终态 │ - └────┬─────┘ └───────────┘ - │ 人类决策 - ▼ - 回到 executing - │ - ┌────┴────┬─────────┐ - ▼ ▼ ▼ -completed failed cancelled -(完成) (失败) (取消) -``` - -### 7.2 终态 -- `completed`:成功完成 -- `failed`:执行失败 -- `cancelled`:被取消 -- `rejected`:被拒绝 - ---- - -## 8. 安全模型总则 - -### 8.1 身份认证 -- 每个 Agent 有唯一身份 -- 支持 HMAC、JWT、OAuth2 等多种认证方式 -- 信任等级机制 - -### 8.2 消息完整性 -- 消息签名机制 -- 防止篡改与伪造 - -### 8.3 机密性 -- 支持端到端加密 -- 敏感载荷加密传输 - -### 8.4 访问控制 -- 基于信任等级的权限控制 -- 群组内基于角色的权限控制 - ---- - -## 9. 非目标 - -以下内容**不在**本原始协议的讨论范围内: - -1. **具体传输协议的实现细节** - 由各传输层实现定义 -2. **特定领域的任务类型** - 由应用层或领域扩展定义 -3. **Agent 内部实现架构** - 仅定义对外接口与行为 -4. **具体编程语言绑定** - 语言无关,可多语言实现 -5. **UI/UX 设计** - 人机界面不在协议范围内 - ---- - -## 10. 参考实现 - -本协议族的参考实现位于:`dp-headless/synapse/` - -| 模块 | 对应协议 | 文件路径 | -|------|---------|---------| -| types 包 | 公共类型定义 | `types/` | -| p2p 包 | A2A 协议 | `p2p/` | -| group 包 | A2N 组群协议 | `group/` | -| externalapi 包 | P2A 调用协议 | `externalapi/` | -| sdk 包 | P2A 客户端 SDK | `sdk/` | - ---- - -## 附录 A:协议演进 - -本原始协议作为顶层指导,保持相对稳定。各具体协议可独立版本化演进,但需遵循本协议定义的核心原则。 - -**版本历史:** -- v1.0.0:初始版本,定义核心概念与设计原则 diff --git a/synapse/docs/02-a2a-protocol.md b/synapse/docs/02-a2a-protocol.md deleted file mode 100644 index 8a5da2a..0000000 --- a/synapse/docs/02-a2a-protocol.md +++ /dev/null @@ -1,465 +0,0 @@ -# A2A 协议(Agent-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -A2A 协议定义了两个 Agent 之间进行点对点(P2P)任务协作的完整规范,包括消息类型、交互流程、状态机、接口定义与错误处理。 - -### 1.1 适用场景 -- 单个任务请求与响应 -- 任务状态实时同步 -- 任务取消 -- 信息补全交互 -- 人类介入决策 - -### 1.2 非适用场景 -- 多 Agent 群组协作(参见 A2N 组群协议) -- 非 Agent 调用方接入(参见 P2A 调用协议) - ---- - -## 2. 消息类型 - -### 2.1 消息类型清单 - -所有消息类型前缀:`p2p:` - -| 消息类型 | 方向 | 说明 | -|---------|------|------| -| `p2p:task_request` | 请求方 → 执行方 | 提交任务请求 | -| `p2p:task_confirm` | 执行方 → 请求方 | 确认接受任务 | -| `p2p:task_reject` | 执行方 → 请求方 | 拒绝任务 | -| `p2p:task_need_info` | 执行方 → 请求方 | 请求补充信息 | -| `p2p:task_info_provided` | 请求方 → 执行方 | 提供补充信息 | -| `p2p:task_status_update` | 执行方 → 请求方 | 任务进度更新 | -| `p2p:task_complete` | 执行方 → 请求方 | 任务完成 | -| `p2p:task_failed` | 执行方 → 请求方 | 任务失败 | -| `p2p:task_cancel` | 请求方 → 执行方 | 取消任务 | -| `p2p:task_ack` | 双向 | 任务级确认 | -| `p2p:ack` | 双向 | 通用确认 | -| `p2p:nack` | 双向 | 通用否定确认(错误) | -| `p2p:heartbeat` | 双向 | 心跳保活 | -| `p2p:capability_query` | 双向 | 查询对方能力 | -| `p2p:capability_response` | 双向 | 返回能力清单 | -| `p2p:task_need_human` | 执行方 → 请求方 | 请求人类介入 | -| `p2p:human_decision` | 请求方 → 执行方 | 人类决策结果 | - -### 2.2 消息类型完整定义 - -参见代码:[types/types.go](../types/types.go) - ---- - -## 3. 任务状态机 - -### 3.1 状态定义 - -| 状态 | 说明 | -|------|------| -| `idle` | 空闲(初始状态) | -| `pending` | 待确认(已发送请求,等待确认) | -| `confirmed` | 已确认(对方接受任务) | -| `executing` | 执行中 | -| `info_needed` | 需要信息 | -| `info_provided` | 信息已提供 | -| `need_human` | 需要人类介入 | -| `human_deciding` | 人类决策中 | -| `human_approved` | 人类已批准 | -| `human_rejected` | 人类已拒绝 | -| `completed` | 已完成(终态) | -| `failed` | 已失败(终态) | -| `cancelled` | 已取消(终态) | -| `rejected` | 已拒绝(终态) | - -### 3.2 状态流转图 - -``` -请求方视角: - -idle → pending → confirmed → executing → completed - ↓ ↓ → failed - rejected info_needed → cancelled - ↑↓ - info_provided - ↓ - need_human - ↑↓ - human_decision -``` - ---- - -## 4. 核心交互流程 - -### 4.1 正常任务提交流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| 1. 提交任务 - | | - |<------- task_confirm / task_reject -| 2. 确认/拒绝 - | | - |<------- task_status_update --------| 3. 进度更新(多次) - | | - |<------- task_complete -------------| 4. 完成通知 - | | - |-------- task_ack ----------------->| 5. 确认收到 - | | -``` - -### 4.2 信息补全流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_info ------------| 发现信息缺失 - | | - |-------- task_info_provided ------->| 补充信息 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.3 人类介入流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |<------- task_need_human -----------| 需要人类决策 - | | - | [人类做出决策] | - | | - |-------- human_decision ----------->| 决策结果 - | | - |<------- task_status_update --------| 继续执行 - | | -``` - -### 4.4 任务取消流程 - -``` -请求方 Agent 执行方 Agent - | | - |-------- task_request ------------->| - | | - |-------- task_cancel -------------->| 取消任务 - | | - |<------- task_ack ------------------| 确认取消 - | | -``` - ---- - -## 5. 接口规范 - -### 5.1 P2P 协议处理器接口 - -**接口定义:** - -```go -type P2PProtocol interface { - // 处理收到的消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h TaskHandler) - - // 设置回调发送器 - SetCallbackSender(s CallbackSender) - - // 获取 Agent 端点 - AgentEndpoint() AgentEndpoint - - // 查询任务状态 - GetTaskStatus(taskID string) (P2PTaskStatus, bool) - - // 列出所有任务 - ListTasks() map[string]P2PTaskStatus -} -``` - -**参考实现:** [p2p/protocol.go](../p2p/protocol.go) - -### 5.2 任务处理器接口 - -```go -type TaskHandler interface { - // 执行任务并返回结果 - ExecuteTask(ctx context.Context, taskType string, payload map[string]interface{}) (any, error) - - // 验证任务是否可执行,返回缺失字段列表和是否可处理 - ValidateTask(taskType string, payload map[string]interface{}) ([]MissingField, bool) - - // 获取能力列表 - GetCapabilities() []string -} -``` - -**说明:** -- `ExecuteTask`:实际执行业务逻辑的入口 -- `ValidateTask`:在任务确认前调用,用于判断是否接受任务或需要补充信息 -- `GetCapabilities`:返回 Agent 支持的任务类型列表 - -### 5.3 回调发送器接口 - -```go -type CallbackSender interface { - // 向远程 Agent 发送消息 - SendCallback(ctx context.Context, endpoint string, msg *UnifiedSynapseMessage) error -} -``` - -**说明:** -- 传输层实现此接口 -- 支持多种传输方式(HTTP、gRPC、WebSocket 等) - -### 5.4 配置项 - -```go -type P2PConfig struct { - MaxRetries int // 最大重试次数(默认 5) - RetryBaseDelay time.Duration // 重试基础延迟(默认 2s,指数退避) - TaskTimeout time.Duration // 任务执行超时(默认 5 分钟) - HeartbeatInterval time.Duration // 心跳间隔(默认 30 秒) -} -``` - ---- - -## 6. 载荷格式 - -### 6.1 TaskRequestPayload(任务请求) - -```json -{ - "task": { - "id": "task-xxx", - "type": "text_generation", - "priority": "normal", - "deadline": "2026-01-01T00:00:00Z", - "payload": { - "prompt": "写一首诗", - "style": "古典" - } - }, - "context": { - "session_id": "sess-xxx", - "parent_task_id": "parent-xxx", - "correlation_id": "corr-xxx", - "metadata": {} - } -} -``` - -### 6.2 TaskConfirmPayload(任务确认) - -```json -{ - "task_id": "task-xxx", - "confirmed": true, - "estimated_duration": 120, - "expected_completion": "2026-01-01T00:02:00Z", - "capabilities_used": ["text_generation"], - "constraints": { - "max_retries": 3, - "fallback_enabled": true - } -} -``` - -### 6.3 TaskRejectPayload(任务拒绝) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "capability_lacking", - "message": "不支持该任务类型", - "details": null - }, - "alternatives": { - "suggested_agent_id": "other-agent", - "retry_after": 300, - "partial_support": false - } -} -``` - -### 6.4 TaskStatusUpdatePayload(状态更新) - -```json -{ - "task_id": "task-xxx", - "status": "executing", - "progress": 50, - "message": "正在生成内容", - "intermediate_result": null -} -``` - -### 6.5 TaskCompletePayload(任务完成) - -```json -{ - "task_id": "task-xxx", - "result": { - "output_type": "text", - "output": "生成的文本内容...", - "metadata": { - "tokens": 1024, - "model": "gpt-4" - } - }, - "summary": "任务已完成" -} -``` - -### 6.6 TaskFailedPayload(任务失败) - -```json -{ - "task_id": "task-xxx", - "error": { - "code": "execution_error", - "message": "模型调用超时", - "recoverable": true, - "details": null - }, - "partial_result": null -} -``` - -### 6.7 TaskNeedInfoPayload(需要信息) - -```json -{ - "task_id": "task-xxx", - "missing_fields": [ - { - "field": "style", - "reason": "未指定生成风格", - "suggested_value": "古典", - "alternatives": ["现代", "浪漫"] - } - ], - "question": "请选择生成风格", - "required_by": "2026-01-01T00:01:00Z" -} -``` - -### 6.8 TaskNeedHumanPayload(需要人类) - -```json -{ - "task_id": "task-xxx", - "reason": { - "code": "ethical_decision", - "message": "涉及伦理决策需要人工审核" - }, - "context": { - "task_summary": "生成一张人物肖像", - "current_progress": 30, - "blocked_reason": "需要确认肖像使用授权" - }, - "options": [ - { - "field": "authorized", - "value": true, - "pros_cons": "继续生成,假设已授权", - "confidence": 70 - } - ], - "escalation_level": 1, - "deadline": "2026-01-01T00:05:00Z" -} -``` - -### 6.9 HumanDecisionPayload(人类决策) - -```json -{ - "task_id": "task-xxx", - "decision_id": "dec-xxx", - "reply_to": "msg-xxx", - "decided_by": { - "user_id": "user-123", - "user_name": "张三", - "role": "reviewer" - }, - "decision": { - "action": "approve", - "approved_fields": { - "authorized": true - }, - "rejection_reason": "" - }, - "notes": "已确认授权", - "timestamp": "2026-01-01T00:03:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 7. 错误码 - -| 错误码 | 说明 | HTTP 状态码(如适用) | -|--------|------|---------------------| -| `message_format_invalid` | 消息格式无效 | 400 | -| `capability_lacking` | 能力不足 | 403 | -| `agent_not_ready` | Agent 未就绪 | 503 | -| `task_not_found` | 任务不存在 | 404 | -| `task_already_completed` | 任务已完成 | 409 | -| `execution_timeout` | 执行超时 | 504 | -| `execution_failed` | 执行失败 | 500 | -| `permission_denied` | 权限不足 | 403 | -| `invalid_params` | 参数无效 | 400 | -| `rate_limited` | 限流 | 429 | - -**完整错误定义:** [types/errors.go](../types/errors.go) - ---- - -## 8. 传输要求 - -### 8.1 HTTP 传输 -- Content-Type: `application/json` -- 请求方法:`POST` -- 端点路径:由 Agent 自行定义,建议 `/synapse/callback` -- 超时:建议 30 秒 - -### 8.2 签名验证(可选) -- 使用 HMAC-SHA256 签名 -- 签名放在 Header:`X-Synapse-Signature` -- 或放在消息体:`signature` 字段 - ---- - -## 9. 参考实现 - -本协议的参考实现位于 `p2p/` 目录: - -| 文件 | 说明 | -|------|------| -| [p2p/protocol.go](../p2p/protocol.go) | P2P 协议核心实现 | -| [types/types.go](../types/types.go) | 数据类型定义 | -| [types/errors.go](../types/errors.go) | 错误定义 | -| [transport/transport.go](../transport/transport.go) | HTTP 传输实现 | - ---- - -## 附录 A:能力声明格式 - -参见 [灵隙原始协议(Synapse Raw Protocol) - Capability](./01-synapse-raw-protocol.md#44-capability能力) diff --git a/synapse/docs/03-a2n-protocol.md b/synapse/docs/03-a2n-protocol.md deleted file mode 100644 index fa70c90..0000000 --- a/synapse/docs/03-a2n-protocol.md +++ /dev/null @@ -1,545 +0,0 @@ -# A2N 协议(Agent-to-N Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -A2N(Agent-to-N)组群协议定义了多个 Agent 组成群组进行协同工作的完整规范,包括群组管理、任务拆分与合并、群体决策、角色与权限等。 - -### 1.1 适用场景 -- 复杂任务的拆分与并行执行(MapReduce 模式) -- 多 Agent 协同完成单一目标 -- 群体投票与共识决策 -- 临时或永久的 Agent 工作组 -- 分级升级(escalation)机制 - -### 1.2 依赖 -- 依赖 A2A 协议的点对点通信能力 -- 群组内成员间的单播通信使用 A2A 协议 - ---- - -## 2. 核心概念 - -### 2.1 Group(群组) -由多个 Agent 组成的协作单元,具有明确的拓扑结构、角色分工与协作规则。 - -### 2.2 Topology(拓扑结构) - -| 拓扑类型 | 说明 | 适用场景 | -|---------|------|---------| -| `star` | 星型,中心 coordinator 协调 | 简单任务分发 | -| `mesh` | 网状,成员间可直接通信 | 对等协作 | -| `chain` | 链式,流水线模式 | 顺序处理 | -| `hierarchical` | 层级型,多层管理 | 大型复杂任务 | -| `fullmesh` | 全连接网状 | 高可靠协作 | - -### 2.3 Role(角色) - -| 角色 | 说明 | 权限 | -|------|------|------| -| `coordinator` | 协调者 | 创建/解散群组、任务拆分、发起投票 | -| `worker` | 工作者 | 执行子任务、提交结果 | -| `reviewer` | 审核者 | 审核结果、发起投票 | -| `observer` | 观察者 | 只读,查看进度 | - -### 2.4 GroupStatus(群组状态) - -| 状态 | 说明 | -|------|------| -| `creating` | 创建中 | -| `active` | 活跃 | -| `frozen` | 冻结(不可执行新任务) | -| `disbanded` | 已解散(终态) | - ---- - -## 3. 消息类型 - -### 3.1 消息类型清单 - -所有消息类型前缀:`group:` 或 `inter_group:` - -#### 群组管理 - -| 消息类型 | 说明 | -|---------|------| -| `group:create` | 创建群组 | -| `group:disband` | 解散群组 | -| `group:join` | 加入群组 | -| `group:leave` | 离开群组 | -| `group:invite` | 邀请加入 | -| `group:accept_invite` | 接受邀请 | -| `group:reject_invite` | 拒绝邀请 | -| `group:member_update` | 成员更新通知 | -| `group:role_change` | 角色变更 | - -#### 群组通信 - -| 消息类型 | 说明 | -|---------|------| -| `group:broadcast` | 广播(所有成员) | -| `group:multicast` | 组播(指定成员) | -| `group:direct` | 群内单播 | -| `group:relay` | 消息中继 | - -#### 任务协作 - -| 消息类型 | 说明 | -|---------|------| -| `group:task_split` | 任务拆分 | -| `group:task_assign` | 任务分配 | -| `group:task_merge` | 结果合并 | -| `group:task_progress` | 子任务进度 | - -#### 共识与投票 - -| 消息类型 | 说明 | -|---------|------| -| `group:vote` | 发起投票 | -| `group:vote_submit` | 提交投票 | -| `group:consensus` | 达成共识 | - -#### 人在回路(HiL) - -| 消息类型 | 说明 | -|---------|------| -| `group:consensus_escalate` | 共识僵局升级给人类 | -| `group:subtask_escalate` | 子任务阻塞升级给人类 | -| `group:human_decision` | 人类决策结果 | -| `inter_group:escalate` | 跨群组升级 | - -**完整定义:** [types/types.go](../types/types.go) - ---- - -## 4. 群组生命周期 - -### 4.1 状态机 - -``` -creating → active → frozen → disbanded - ↑ ↓ - └─────────┘ - 解冻 -``` - -### 4.2 群组创建流程 - -``` -创建者 被邀请成员 - | | - |------ group:invite -------------->| 发送邀请 - | | - |<----- group:accept_invite --------| 接受邀请 - | | - |------ group:member_update ------->| 通知成员更新 - | | - [群组创建完成,状态变为 active] | -``` - -### 4.3 群组解散流程 - -``` -coordinator 所有成员 - | | - |------ group:disband ------------->| 通知解散 - | | - [群组状态变为 disbanded] | -``` - ---- - -## 5. 任务协作流程 - -### 5.1 MapReduce 模式(拆分-执行-合并) - -``` - ┌──────────────┐ - │ coordinator │ - └──────┬───────┘ - │ - group:task_split(拆分任务) - │ - ┌────────────────┼────────────────┐ - ▼ ▼ ▼ - ┌─────────┐ ┌─────────┐ ┌─────────┐ - │ worker1 │ │ worker2 │ │ worker3 │ - └────┬────┘ └────┬────┘ └────┬────┘ - │ │ │ - │ 执行子任务 │ 执行子任务 │ 执行子任务 - │ │ │ - ▼ ▼ ▼ - 子任务结果 子任务结果 子任务结果 - └────────────────┼────────────────┘ - │ - group:task_merge(合并结果) - ▼ - ┌──────────────┐ - │ 最终结果 │ - └──────────────┘ -``` - -### 5.2 详细流程 - -1. **任务拆分阶段** - - coordinator 接收原始任务 - - 将任务拆分为多个子任务(subtask) - - 为每个子任务指定执行的 worker - - 定义合并策略(merge strategy) - -2. **并行执行阶段** - - 各 worker 并行执行子任务 - - 定期上报进度(`group:task_progress`) - - 子任务完成后上报结果 - -3. **结果合并阶段** - - 所有子任务完成后,coordinator 合并结果 - - 根据合并策略决定最终结果 - - 输出最终结果 - ---- - -## 6. 合并策略(Merge Strategy) - -| 策略 | 说明 | -|------|------| -| `all_success` | 全部成功才认为成功,否则失败 | -| `majority` | 多数子任务成功即可,取多数结果 | -| `any_complete` | 任意一个完成即返回结果 | -| `priority` | 按优先级,高优先级子任务结果优先 | - ---- - -## 7. 投票与共识 - -### 7.1 投票流程 - -``` -发起者 投票者 - | | - |-------- group:vote -------------->| 发起投票 - | | - |<------- group:vote_submit --------| 提交投票 - | | - [计票,判断是否达到阈值] | - | | - |-------- group:consensus --------->| 公布结果 - | | -``` - -### 7.2 投票规则 - -- `threshold`:通过阈值(0-1),如 0.5 表示过半 -- `deadline`:投票截止时间 -- `voters`:有投票权的成员列表 -- 超时未投票视为弃权 - -### 7.3 共识僵局(Consensus Deadlock) - -当投票无法达成共识(如平票、未达阈值且超时)时,可升级给人类决策。 - ---- - -## 8. 人在回路(HiL) - -群组协作中有两种升级场景: - -### 8.1 共识僵局升级 -投票无法达成共识时,升级给人类裁决。 - -**消息:** `group:consensus_escalate` - -### 8.2 子任务阻塞升级 -某个子任务遇到无法自动解决的问题时,升级给人类。 - -**消息:** `group:subtask_escalate` - -### 8.3 跨群组升级 -问题超出当前群组能力时,可升级到上级群组或人类。 - -**消息:** `inter_group:escalate` - ---- - -## 9. 接口规范 - -### 9.1 GroupProtocol 接口 - -```go -type GroupProtocol interface { - // 处理群组消息 - HandleMessage(ctx context.Context, msg *UnifiedSynapseMessage) (*UnifiedSynapseMessage, error) - - // 设置任务处理器 - SetTaskHandler(h GroupTaskHandler) - - // 查询群组列表 - GetGroups() []*AgentGroup - - // 查询特定群组 - GetGroup(groupID string) (*AgentGroup, bool) -} -``` - -**参考实现:** [group/protocol.go](../group/protocol.go) - -### 9.2 GroupTaskHandler 接口 - -```go -type GroupTaskHandler interface { - // 执行子任务 - ExecuteSubtask(ctx context.Context, subtaskID string, payload map[string]interface{}) (any, error) - - // 合并多个子任务结果 - MergeResults(results []SubtaskResult, strategy MergeStrategy) (any, error) - - // 验证任务是否可拆分,返回拆分方案 - ValidateTaskSplit(taskType string, requirements map[string]interface{}) ([]Subtask, bool) -} -``` - -**说明:** -- `ExecuteSubtask`:执行单个子任务的业务逻辑 -- `MergeResults`:根据策略合并多个子任务的结果 -- `ValidateTaskSplit`:验证任务是否可拆分,并给出拆分方案 - -### 9.3 配置项 - -```go -type GroupConfig struct { - MaxGroupSize int // 最大群组人数(默认 20) - MaxSubtasks int // 最大子任务数(默认 50) - ConsensusTimeout time.Duration // 共识超时(默认 5 分钟) - TaskTimeout time.Duration // 任务超时(默认 10 分钟) -} -``` - ---- - -## 10. 载荷格式 - -### 10.1 GroupCreatePayload(创建群组) - -```json -{ - "group": { - "name": "视频制作组", - "topology": "star", - "config": { - "allow_self_leave": true, - "requires_approval": false, - "consensus_required": false, - "consensus_threshold": 0.5, - "broadcast_mode": "all" - }, - "initial_members": [ - { - "agent_id": "worker-1", - "system_id": "sys-a", - "endpoint": "http://worker1/synapse" - } - ], - "roles": [ - { - "id": "coordinator", - "name": "协调者", - "permissions": ["create", "disband", "split", "vote"], - "max_tasks": 10 - } - ] - } -} -``` - -### 10.2 GroupTaskSplitPayload(任务拆分) - -```json -{ - "original_task": { - "id": "task-xxx", - "type": "video_generation", - "requirements": { - "script": "xxx", - "duration": 60 - }, - "deadline": "2026-01-01T00:10:00Z" - }, - "subtasks": [ - { - "id": "sub-1", - "description": "生成脚本", - "assigned_to": "writer-agent", - "dependencies": [], - "estimated_duration": 120, - "priority": 1 - }, - { - "id": "sub-2", - "description": "生成配音", - "assigned_to": "voice-agent", - "dependencies": ["sub-1"], - "estimated_duration": 180, - "priority": 2 - } - ], - "merge_strategy": "all_success" -} -``` - -### 10.3 GroupTaskMergePayload(结果合并) - -```json -{ - "original_task_id": "task-xxx", - "subtask_results": [ - { - "subtask_id": "sub-1", - "assigned_to": "writer-agent", - "status": "success", - "result": { "script": "..." }, - "completed_at": "2026-01-01T00:02:00Z" - } - ], - "merge_strategy_used": "all_success", - "merged_result": { - "video_url": "http://..." - }, - "consensus_achieved": true -} -``` - -### 10.4 GroupVotePayload(投票) - -```json -{ - "vote_id": "vote-xxx", - "question": "是否采用方案A?", - "options": ["方案A", "方案B", "方案C"], - "voters": ["agent-1", "agent-2", "agent-3"], - "deadline": "2026-01-01T00:05:00Z", - "threshold": 0.66, - "status": "open", - "votes": [] -} -``` - -### 10.5 GroupConsensusEscalatePayload(共识升级) - -```json -{ - "vote_id": "vote-xxx", - "escalation_id": "esc-xxx", - "question": "是否采用方案A?", - "votes": [ - { - "voter_id": "agent-1", - "voter_role": "reviewer", - "option": "方案A", - "reason": "质量更好" - } - ], - "consensus_status": { - "required_threshold": 0.66, - "actual_threshold": 0.33, - "leading_option": "方案A", - "options_tied": false - }, - "escalate_reason": { - "code": "no_consensus", - "message": "无法达成共识" - }, - "escalation_level": 2, - "deadline": "2026-01-01T00:10:00Z" -} -``` - -**完整载荷定义:** [types/types.go](../types/types.go) - ---- - -## 11. 数据结构 - -### 11.1 AgentGroup(群组) - -```go -type AgentGroup struct { - ID string - Name string - Topology GroupTopology - CreatedBy string - CreatedAt Timestamp - Config GroupConfig - Members []GroupMember - Roles []GroupRole - Status GroupStatus -} -``` - -### 11.2 GroupMember(群组成员) - -```go -type GroupMember struct { - AgentID string - AgentName string - Role string - JoinedAt Timestamp - Status GroupMemberStatus - Capabilities []string - LoadFactor float64 // 负载因子 0-1,用于任务分配 -} -``` - -### 11.3 Subtask(子任务) - -```go -type Subtask struct { - ID string - Description string - AssignedTo string - Dependencies []string - EstimatedDuration int - Priority int -} -``` - ---- - -## 12. 错误码 - -群组协议特有错误码: - -| 错误码 | 说明 | -|--------|------| -| `group_not_found` | 群组不存在 | -| `group_not_active` | 群组不活跃 | -| `group_full` | 群组已满 | -| `already_member` | 已是成员 | -| `not_group_member` | 不是群组成员 | -| `member_not_found` | 成员不存在 | -| `permission_denied` | 权限不足 | -| `invalid_params` | 参数无效 | - ---- - -## 13. 参考实现 - -本协议的参考实现位于 `group/` 目录: - -| 文件 | 说明 | -|------|------| -| [group/protocol.go](../group/protocol.go) | 群组协议核心实现 | -| [types/types.go](../types/types.go) | 群组相关数据类型 | - ---- - -## 附录 A:与 A2A 协议的关系 - -- 群组内的点对点通信使用 A2A 协议 -- 群组协议在 A2A 协议之上提供群组管理、任务拆分合并、共识投票等能力 -- 群组消息同样使用统一消息信封(`UnifiedSynapseMessage`),通过 `group_id` 字段标识群组上下文 diff --git a/synapse/docs/04-p2a-protocol.md b/synapse/docs/04-p2a-protocol.md deleted file mode 100644 index 70dc4ac..0000000 --- a/synapse/docs/04-p2a-protocol.md +++ /dev/null @@ -1,503 +0,0 @@ -# P2A 协议(Person/Program-to-Agent Protocol) - -> 版本:1.0.0 -> 状态:草案 -> 类型:实现规范 -> 基于:[灵隙原始协议(Synapse Raw Protocol) v1.0.0](./01-synapse-raw-protocol.md) - ---- - -## 1. 概述 - -P2A(Person/Program-to-Agent)调用协议定义了**非 Agent 调用方**(如普通后端服务、前端应用、第三方系统、人类用户)如何调用 Agent 能力的规范。 - -本协议将 A2A 协议的复杂性封装起来,提供简洁的 RESTful API,使调用方无需了解 A2A 协议细节即可使用 Agent 能力。 - -### 1.1 适用场景 -- 前端应用直接调用 Agent 能力 -- 后端业务系统集成 Agent 服务 -- 第三方开发者通过 API 接入 -- 无需实现完整 A2A 协议的调用方 - -### 1.2 设计原则 -- **简单易用**:标准 RESTful API,JSON 格式 -- **两种模式**:回调模式 + 轮询模式,调用方按需选择 -- **认证简单**:API Key 认证,无需 HMAC 签名 -- **文件支持**:支持 multipart/form-data 上传文件 -- **错误友好**:清晰的错误码和错误信息 - -### 1.3 与 A2A 协议的关系 - -``` -外部调用方 ──P2A 协议──▶ External API Layer ──A2A 协议──▶ Agent -``` - -P2A 协议是 A2A 协议的"简化入口",所有请求最终会转换为 灵隙消息发送给 Agent。 - ---- - -## 2. 认证方式 - -### 2.1 API Key 认证 -- 在 HTTP Header 中传递:`X-API-Key: {api_key}` -- 或在 URL Query 中传递:`?api_key={api_key}` -- 如果服务端未配置 API Key,则跳过认证 - -### 2.2 回调验证(可选) -如果调用方提供了 `callback_token`,则服务端在回调时会在 Header 中带上 `X-Callback-Token`,用于调用方验证回调来源。 - ---- - -## 3. API 端点 - -所有端点默认前缀:`/api/v1/synapse` - -### 3.1 端点清单 - -| 方法 | 路径 | 说明 | -|------|------|------| -| POST | `/task` | 提交任务(JSON) | -| POST | `/task/multipart` | 提交任务(带文件上传) | -| GET | `/task/{task_id}` | 获取任务详情 | -| GET | `/task/{task_id}/status` | 获取任务状态(简化版) | -| GET | `/tasks` | 获取任务列表 | -| POST | `/task/{task_id}/cancel` | 取消任务 | -| GET | `/capabilities` | 获取能力清单 | -| POST | `/callback` | 接收回调(调用方实现) | - ---- - -## 4. 任务提交 - -### 4.1 提交任务(JSON) - -**请求:** -```http -POST /api/v1/synapse/task -Content-Type: application/json -X-API-Key: your-api-key - -{ - "task_type": "text_generation", - "payload": { - "prompt": "写一首诗", - "style": "古典" - }, - "external_task_id": "my-task-001", - "priority": "normal", - "callback_url": "https://your-domain.com/callback", - "callback_token": "your-callback-token" -} -``` - -**请求字段说明:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型,如 `video_generation`, `image_generation` | -| `payload` | object | 是 | 任务参数,具体结构取决于 task_type | -| `external_task_id` | string | 否 | 调用方的任务 ID,用于关联 | -| `priority` | string | 否 | 优先级:`low`, `normal`, `high`, `urgent`,默认 `normal` | -| `callback_url` | string | 否 | 回调 URL,不提供则需轮询 | -| `callback_token` | string | 否 | 回调验证 token | - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "received", - "message": "任务已接收" -} -``` - -**响应字段说明:** - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | bool | 是否成功 | -| `task_id` | string | 服务端生成的任务 ID | -| `status` | string | 初始状态,通常为 `received` | -| `message` | string | 提示信息 | -| `error` | string | 错误信息(失败时) | - -### 4.2 提交任务(Multipart 带文件) - -**请求:** -```http -POST /api/v1/synapse/task/multipart -Content-Type: multipart/form-data -X-API-Key: your-api-key - -------WebKitFormBoundary -Content-Disposition: form-data; name="task_type" - -image_generation - -------WebKitFormBoundary -Content-Disposition: form-data; name="payload" - -{"prompt":"一只猫","style":"写实"} - -------WebKitFormBoundary -Content-Disposition: form-data; name="priority" - -normal - -------WebKitFormBoundary -Content-Disposition: form-data; name="file"; filename="reference.jpg" -Content-Type: image/jpeg - -[二进制数据] - -------WebKitFormBoundary-- -``` - -**表单字段:** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `task_type` | string | 是 | 任务类型 | -| `payload` | string(JSON) | 是 | 任务参数(JSON 字符串) | -| `external_task_id` | string | 否 | 外部任务 ID | -| `priority` | string | 否 | 优先级 | -| `callback_url` | string | 否 | 回调 URL | -| `callback_token` | string | 否 | 回调 token | -| `file` | file | 否 | 上传的文件(可多个) | - -**响应:** 同 JSON 提交方式 - ---- - -## 5. 任务查询 - -### 5.1 获取任务详情 - -**请求:** -```http -GET /api/v1/synapse/task/{task_id} -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task": { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z", - "completed_at": "2026-01-01T00:01:00Z", - "eta": "2026-01-01T00:01:00Z", - "result": { - "text": "生成的文本...", - "metadata": { "tokens": 1024 } - }, - "error": null, - "external_task_id": "my-task-001" - } -} -``` - -**任务状态:** - -| 状态 | 说明 | -|------|------| -| `received` | 已接收 | -| `processing` | 处理中 | -| `completed` | 已完成 | -| `failed` | 已失败 | -| `cancelled` | 已取消 | - -### 5.2 获取任务状态(简化版) - -**请求:** -```http -GET /api/v1/synapse/task/{task_id}/status -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "processing", - "progress": 50 -} -``` - -### 5.3 获取任务列表 - -**请求:** -```http -GET /api/v1/synapse/tasks?status=processing&limit=20&offset=0 -X-API-Key: your-api-key -``` - -**查询参数:** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `status` | string | 否 | 按状态过滤 | -| `limit` | int | 否 | 每页数量,默认 20 | -| `offset` | int | 否 | 偏移量,默认 0 | - -**响应:** -```json -{ - "success": true, - "tasks": [ - { - "id": "task-abc123", - "type": "text_generation", - "status": "completed", - "progress": 100, - "created_at": "2026-01-01T00:00:00Z", - "updated_at": "2026-01-01T00:01:00Z" - } - ], - "total": 1, - "limit": 20, - "offset": 0, - "has_more": false -} -``` - ---- - -## 6. 任务取消 - -**请求:** -```http -POST /api/v1/synapse/task/{task_id}/cancel -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "task_id": "task-abc123", - "status": "cancelled", - "message": "任务已取消" -} -``` - ---- - -## 7. 能力查询 - -**请求:** -```http -GET /api/v1/synapse/capabilities -X-API-Key: your-api-key -``` - -**响应:** -```json -{ - "success": true, - "capabilities": { - "agent_id": "my-agent", - "agent_name": "我的Agent", - "system_id": "my-system", - "protocol_version": "1.0.0", - "supported_task_types": [ - { - "type": "text_generation", - "name": "文本生成", - "description": "生成各种类型的文本内容", - "estimated_time": "30s", - "input_schema": "...", - "output_schema": "..." - } - ], - "supported_transport_modes": ["callback", "polling"], - "max_file_size": 104857600, - "max_concurrent_tasks": 10, - "support_progress_updates": true, - "support_streaming": false, - "support_hil": true, - "support_groups": true - } -} -``` - ---- - -## 8. 回调机制 - -如果调用方提供了 `callback_url`,服务端会在任务状态变化时主动回调。 - -### 8.1 回调请求 - -```http -POST {callback_url} -Content-Type: application/json -X-Callback-Token: {callback_token} - -{ - "task_id": "task-abc123", - "status": "completed", - "progress": 100, - "message": "任务已完成", - "result": { - "text": "生成的文本..." - }, - "error": null, - "timestamp": "2026-01-01T00:01:00Z" -} -``` - -### 8.2 回调类型 - -| 触发时机 | 说明 | -|---------|------| -| 任务开始处理 | `status=processing`, `progress=0` | -| 进度更新 | `status=processing`, `progress=N` | -| 任务完成 | `status=completed`, `progress=100`, 包含 result | -| 任务失败 | `status=failed`, 包含 error | -| 任务取消 | `status=cancelled` | - -### 8.3 回调响应 - -调用方应返回 2xx 状态码表示成功接收。如果返回非 2xx,服务端会重试(指数退避,最多 5 次)。 - ---- - -## 9. 错误处理 - -### 9.1 错误响应格式 - -```json -{ - "success": false, - "error": "invalid_task_type", - "message": "不支持的任务类型" -} -``` - -### 9.2 错误码列表 - -| 错误码 | HTTP 状态码 | 说明 | -|--------|------------|------| -| `unauthorized` | 401 | API Key 无效或缺失 | -| `invalid_request` | 400 | 请求格式无效 | -| `invalid_task_type` | 400 | 任务类型不支持 | -| `invalid_params` | 400 | 参数无效 | -| `task_not_found` | 404 | 任务不存在 | -| `task_already_completed` | 409 | 任务已完成,无法取消 | -| `file_too_large` | 413 | 文件过大 | -| `rate_limited` | 429 | 请求过于频繁 | -| `internal_error` | 500 | 服务内部错误 | -| `service_unavailable` | 503 | 服务不可用 | - ---- - -## 10. SDK 客户端接口 - -为方便调用方集成,提供 SDK 客户端。 - -### 10.1 SDK 初始化 - -```go -client := sdk.NewClient(sdk.ClientConfig{ - BaseURL: "https://agent-api.example.com", - APIKey: "your-api-key", - Timeout: 30 * time.Second, -}) -``` - -### 10.2 SDK 方法清单 - -| 方法 | 说明 | -|------|------| -| `SubmitTask(ctx, req)` | 提交任务(JSON) | -| `SubmitTaskWithFiles(ctx, req, files)` | 提交任务(带文件) | -| `GetTask(ctx, taskID)` | 获取任务详情 | -| `GetTaskStatus(ctx, taskID)` | 获取任务状态 | -| `ListTasks(ctx, status, limit, offset)` | 获取任务列表 | -| `CancelTask(ctx, taskID)` | 取消任务 | -| `GetCapabilities(ctx)` | 获取能力清单 | -| `WaitForTask(ctx, taskID, interval)` | 等待任务完成(轮询) | - -### 10.3 数据结构 - -```go -type TaskRequest struct { - TaskType string - Payload map[string]any - ExternalTaskID string - Priority string - CallbackURL string - CallbackToken string -} - -type TaskInfo struct { - ID string - Type string - Status string - Progress int - Message string - CreatedAt string - UpdatedAt string - CompletedAt string - ETA string - Result map[string]any - Error *TaskError - ExternalTaskID string -} -``` - -**完整 SDK 实现:** [sdk/client.go](../sdk/client.go) - ---- - -## 11. 参考实现 - -本协议的参考实现: - -| 模块 | 文件路径 | 说明 | -|------|---------|------| -| 服务端 | [externalapi/handler.go](../externalapi/handler.go) | External API Handler | -| 客户端 SDK | [sdk/client.go](../sdk/client.go) | Go 语言 SDK | - ---- - -## 附录 A:调用模式选择 - -### 回调模式 vs 轮询模式 - -| 对比项 | 回调模式 | 轮询模式 | -|--------|---------|---------| -| 实时性 | 高,状态变化即时通知 | 低,取决于轮询间隔 | -| 实现复杂度 | 调用方需提供公网可访问的回调接口 | 简单,只需调用 GET 接口 | -| 网络要求 | 调用方需要公网可达 | 只需调用方能访问服务端 | -| 适用场景 | 生产环境、需要实时通知 | 开发测试、内网环境 | - -### 选择建议 - -- **有公网服务器**:使用回调模式 -- **本地开发 / 内网环境**:使用轮询模式 -- **长时间任务**:建议回调模式,避免频繁轮询 -- **短任务(<10s)**:可直接同步等待或高频轮询 - ---- - -## 附录 B:从 A2A 协议到 P2A 协议的映射 - -| 灵隙概念 | P2A 对应 | 说明 | -|---------|---------|------| -| `p2p:task_request` | `POST /task` | 任务提交 | -| `p2p:task_status_update` | 回调 / GET /task | 状态更新 | -| `p2p:task_complete` | 回调(status=completed) | 任务完成 | -| `p2p:task_failed` | 回调(status=failed) | 任务失败 | -| `p2p:task_cancel` | `POST /task/{id}/cancel` | 任务取消 | -| `p2p:capability_query` | `GET /capabilities` | 能力查询 | -| Agent 身份 | API Key | 简化认证 | -| HMAC 签名 | Callback Token | 简化验证 | diff --git a/synapse/docs/05-sdk-implementation.md b/synapse/docs/05-sdk-implementation.md deleted file mode 100644 index 684a996..0000000 --- a/synapse/docs/05-sdk-implementation.md +++ /dev/null @@ -1,519 +0,0 @@ -# SDK 实现说明 - -> 版本:1.0.0 -> 更新日期:2026-06-27 -> 协议版本:1.0.0 -> 关联协议: -> - [A2A 协议](./02-a2a-protocol.md) -> - [A2N 协议](./03-a2n-protocol.md) -> - [P2A 协议](./04-p2a-protocol.md) - ---- - -## 1. 概述 - -SDK 按照灵隙协议族(Synapse Protocol Suite)的三个子协议进行了模块化设计,分为三个子包,命名与协议名保持一致: - -``` -┌─────────────────────────────────────────────────────────────┐ -│ SDK (sdk/) │ -├──────────────┬───────────────────┬───────────────────────────┤ -│ sdk/p2a │ sdk/a2a │ sdk/a2n │ -│ P2A 协议 │ A2A 协议 │ A2N 协议 │ -│ (外部调用) │ (Agent间通信) │ (群组协作) │ -│ ✅ 完整实现 │ ✅ 完整实现 │ ✅ 完整实现 │ -└──────────────┴───────────────────┴───────────────────────────┘ -``` - ---- - -## 2. SDK 目录结构 - -``` -sdk/ -├── doc.go # SDK 包文档(使用说明) -├── p2a/ -│ └── client.go # P2A 协议 - 外部调用客户端 -├── a2a/ -│ └── client.go # A2A 协议 - Agent间通信客户端 -└── a2n/ - └── client.go # A2N 协议 - 群组协作客户端 -``` - ---- - -## 3. 第一部分:sdk/p2a - P2A 协议 - -**协议对应**:[P2A 协议](./04-p2a-protocol.md) -**版本**:1.0.0 -**用途**:非 Agent 调用方(前端、后端服务、第三方应用)通过 REST API 调用 Agent 能力 - -### 3.1 实现对应关系 - -| P2A 协议功能 | SDK 方法 | 位置 | -|-------------|---------|------| -| 认证方式 | `setHeaders()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 提交任务(JSON) | `SubmitTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 提交任务(Multipart) | `SubmitTaskWithFiles()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务详情 | `GetTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务状态(简化版) | `GetTaskStatus()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 获取任务列表 | `ListTasks()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 取消任务 | `CancelTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 能力查询 | `GetCapabilities()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 回调验证 | `VerifyCallback()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | -| 轮询等待 | `WaitForTask()` | [sdk/p2a/client.go](../sdk/p2a/client.go) | - -### 3.2 核心数据结构 - -```go -// Client 客户端 -type Client struct { - baseURL string - apiKey string - httpClient *http.Client -} - -// 配置 -type ClientConfig struct { - BaseURL string - APIKey string - Timeout time.Duration - MaxRetries int -} - -// 任务请求 -type TaskRequest struct { - TaskType string - Payload map[string]any - ExternalTaskID string - Priority string - CallbackURL string - CallbackToken string -} - -// 任务信息 -type TaskInfo struct { - ID string - Type string - Status string - Progress int - Result map[string]any - Error *TaskError -} - -// 文件上传参数 -type FileParam struct { - FieldName string - Filename string - Data []byte - MimeType string -} -``` - -### 3.3 使用示例 - -```go -import "dp-headless/synapse/sdk/p2a" - -client := p2a.NewClient(p2a.ClientConfig{ - BaseURL: "https://agent-api.example.com", - APIKey: "your-api-key", -}) - -// 提交任务并等待完成 -taskInfo, err := client.CreateAndWait(ctx, "text_generation", map[string]any{ - "prompt": "写一首诗", - "style": "古典", -}, 5*time.Second) - -// 使用回调模式 -resp, err := client.CreateWithCallback(ctx, "image_generation", payload, - "https://your-domain.com/callback", - "callback-token", -) -``` - ---- - -## 4. 第二部分:sdk/a2a - A2A 协议 - -**协议对应**:[A2A 协议](./02-a2a-protocol.md) -**版本**:1.0.0 -**用途**:Agent 之间的点对点通信,包含消息发送、签名验证、回调处理 - -### 4.1 实现对应关系 - -| A2A 协议功能 | SDK 方法 | 位置 | -|------------|---------|------| -| 发送任务请求 | `SendTaskRequest()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 发送任务取消 | `SendTaskCancel()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 发送人类决策 | `SendHumanDecision()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 查询能力 | `SendCapabilityQuery()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 消息签名 | `signMessage()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 签名验证 | `verifySignature()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 任务状态管理 | `GetTaskState()`, `ListTasks()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 等待任务完成 | `WaitForTask()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | -| 回调服务 | `startCallbackServer()` | [sdk/a2a/client.go](../sdk/a2a/client.go) | - -### 4.2 核心数据结构 - -```go -// Client A2A客户端 -type Client struct { - agentEndpoint types.AgentEndpoint - authSecret string - callbackHandler MessageCallbackHandler - tasks map[string]*A2ATaskState -} - -// 配置 -type ClientConfig struct { - AgentEndpoint types.AgentEndpoint - AuthSecret string - CallbackPort int - Timeout time.Duration - MaxRetries int -} - -// 消息回调处理器接口 -type MessageCallbackHandler interface { - HandleTaskRequest(ctx context.Context, msg *types.UnifiedSynapseMessage) (*types.UnifiedSynapseMessage, error) - HandleTaskStatusUpdate(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskComplete(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleTaskFailed(ctx context.Context, msg *types.UnifiedSynapseMessage) error - HandleNeedHuman(ctx context.Context, msg *types.UnifiedSynapseMessage) error -} - -// 任务状态 -type A2ATaskState struct { - TaskID string - Status types.P2PTaskStatus - Progress int - Message string - Result any - Error *types.SynapseError -} -``` - -### 4.3 使用示例 - -```go -import "dp-headless/synapse/sdk/a2a" - -a2aClient, err := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "my-agent", - AgentName: "我的Agent", - SystemID: "my-system", - Endpoint: "http://localhost:8080/synapse/callback", - }, - AuthSecret: "my-hmac-secret", - CallbackPort: 8080, -}) - -// 设置消息处理器 -a2aClient.SetMessageHandler(&myHandler{}) - -// 发送任务请求给其他Agent -taskID, err := a2aClient.SendTaskRequest(ctx, targetAgent, "video_generation", map[string]any{ - "prompt": "生成一段视频", -}) -``` - ---- - -## 5. 第三部分:sdk/a2n - A2N 协议 - -**协议对应**:[A2N 协议](./03-a2n-protocol.md) -**版本**:1.0.0 -**用途**:多 Agent 群组协作,包含群组管理、任务拆分合并、投票、升级 - -### 5.1 实现对应关系 - -| A2N 协议功能 | SDK 方法 | 位置 | -|------------|---------|------| -| 创建群组 | `CreateGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 加入群组 | `JoinGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 离开群组 | `LeaveGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 解散群组 | `DisbandGroup()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 提交群组任务 | `SubmitGroupTask()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 发送子任务结果 | `SendSubtaskResult()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 发起投票 | `InitiateVote()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 提交投票 | `SubmitVote()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 广播消息 | `Broadcast()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | -| 升级到人类 | `EscalateToHuman()` | [sdk/a2n/client.go](../sdk/a2n/client.go) | - -### 5.2 核心数据结构 - -```go -// Client A2N客户端 -type Client struct { - a2aClient *a2a.Client - groups map[string]*GroupState - eventHandler GroupEventHandler -} - -// 配置 -type ClientConfig struct { - A2AClient *a2a.Client - EventHandler GroupEventHandler -} - -// 群组状态 -type GroupState struct { - GroupID string - Name string - Topology types.GroupTopology - Status types.GroupStatus - Members []types.GroupMember - Role string // "coordinator" | "worker" -} - -// 群组事件处理器接口 -type GroupEventHandler interface { - OnGroupCreated(ctx context.Context, groupID string) error - OnGroupDisbanded(ctx context.Context, groupID string) error - OnMemberJoined(ctx context.Context, groupID string, member types.GroupMember) error - OnMemberLeft(ctx context.Context, groupID string, agentID string) error - OnTaskSplit(ctx context.Context, groupID string, originalTaskID string, subtasks []types.Subtask) error - OnSubtaskProgress(ctx context.Context, groupID string, subtaskID string, progress int) error - OnTaskMerged(ctx context.Context, groupID string, originalTaskID string, result any) error - OnVoteInitiated(ctx context.Context, groupID string, vote types.GroupVotePayload) error - OnVoteResult(ctx context.Context, groupID string, voteID string, option string, passed bool) error - OnEscalation(ctx context.Context, groupID string, escalationID string, level int) error - OnBroadcast(ctx context.Context, groupID string, sender types.AgentEndpoint, message []byte) error -} -``` - -### 5.3 使用示例 - -```go -import ( - "dp-headless/synapse/sdk/a2n" - "dp-headless/synapse/sdk/a2a" -) - -// 创建A2A客户端 -a2aClient, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: myEndpoint, -}) - -// 创建A2N客户端 -a2nClient, err := a2n.NewClient(&a2n.ClientConfig{ - A2AClient: a2aClient, - EventHandler: &myGroupHandler{}, -}) - -// 创建群组 -group, err := a2nClient.CreateGroup(ctx, "视频制作组", types.GroupTopologyStar, nil, members) - -// 作为Coordinator,提交任务 -subtasks, err := a2nClient.SubmitGroupTask(ctx, group.GroupID, "video_generation", - map[string]any{"script": "..."}, - types.MergeAllSuccess, -) - -// 发起投票 -voteID, err := a2nClient.InitiateVote(ctx, group.GroupID, - "选择哪个方案?", - []string{"方案A", "方案B"}, - voterIDs, - 0.5, - 5*time.Minute, -) -``` - ---- - -## 6. SDK 架构总览 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ SDK (dp-headless/synapse/sdk) │ -├─────────────────────────────────────────────────────────────┤ -│ doc.go │ -│ ├── 包文档和使用说明 │ -│ └── 指向各子包的链接 │ -├────────────────┬────────────────┬─────────────────────────┤ -│ sdk/p2a │ sdk/a2a │ sdk/a2n │ -│ │ │ │ -│ P2A协议 │ 灵隙协议 │ A2N协议 │ -│ │ │ │ -│ ├── Client │ ├── Client │ ├── Client │ -│ ├── 配置 │ ├── 配置 │ ├── 配置 │ -│ ├── 任务操作 │ ├── 消息发送 │ ├── 群组管理 │ -│ ├── 能力查询 │ ├── 任务状态 │ ├── 任务协作 │ -│ └── 回调验证 │ ├── 回调服务 │ ├── 投票 │ -│ │ └── 签名 │ └── 升级 │ -└────────────────┴────────────────┴─────────────────────────┘ -``` - ---- - -## 7. 快速开始 - -### 7.1 P2A 调用(外部调用者) - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/p2a" -) - -func main() { - client := p2a.NewClient(p2a.ClientConfig{ - BaseURL: "https://agent.example.com", - APIKey: "your-api-key", - }) - - ctx := context.Background() - - // 方式1: 轮询等待 - result, err := client.CreateAndWait(ctx, "text_generation", map[string]any{ - "prompt": "写一首诗", - }, 5*time.Second) - if err != nil { - fmt.Println("Error:", err) - } - fmt.Printf("Result: %v\n", result.Result) - - // 方式2: 回调模式 - resp, err := client.CreateWithCallback(ctx, "image_generation", - map[string]any{"prompt": "一只猫"}, - "https://your-domain.com/callback", - "token", - ) - fmt.Printf("Task ID: %s\n", resp.TaskID) -} -``` - -### 7.2 灵隙 通信(Agent 间) - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/a2a" - "dp-headless/synapse/types" -) - -func main() { - client, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: types.AgentEndpoint{ - AgentID: "agent-001", - AgentName: "Agent 001", - SystemID: "my-system", - Endpoint: "http://localhost:8080/synapse/callback", - }, - AuthSecret: "secret-key", - CallbackPort: 8080, - }) - - ctx := context.Background() - target := types.AgentEndpoint{ - AgentID: "agent-002", - Endpoint: "http://agent-002:8080/synapse/callback", - } - - // 发送任务请求 - taskID, err := client.SendTaskRequest(ctx, target, "data_analysis", map[string]any{ - "dataset": "sales.csv", - }) - fmt.Printf("Task ID: %s\n", taskID) - - // 等待完成 - state, err := client.WaitForTask(ctx, taskID, 5*time.Minute) - fmt.Printf("Status: %s\n", state.Status) -} -``` - -### 7.3 A2N 群组协作 - -```go -package main - -import ( - "context" - "fmt" - - "dp-headless/synapse/sdk/a2n" - "dp-headless/synapse/sdk/a2a" - "dp-headless/synapse/types" -) - -func main() { - a2aClient, _ := a2a.NewClient(&a2a.ClientConfig{ - AgentEndpoint: myEndpoint, - }) - - a2nClient, _ := a2n.NewClient(&a2n.ClientConfig{ - A2AClient: a2aClient, - }) - - ctx := context.Background() - - // 创建群组 - group, _ := a2nClient.CreateGroup(ctx, "协作组", types.GroupTopologyStar, nil, []types.AgentEndpoint{ - {AgentID: "member-1", Endpoint: "http://member-1:8080"}, - {AgentID: "member-2", Endpoint: "http://member-2:8080"}, - }) - - fmt.Printf("Group ID: %s\n", group.GroupID) - - // 提交任务 - subtasks, _ := a2nClient.SubmitGroupTask(ctx, group.GroupID, "video_generation", - map[string]any{"script": "..."}, - types.MergeAllSuccess, - ) - - fmt.Printf("Split into %d subtasks\n", len(subtasks)) -} -``` - ---- - -## 8. 协议与包名对应关系 - -| 协议名称 | 协议文档 | SDK 包名 | 包路径 | -|---------|---------|---------|--------| -| 灵隙原始协议(Synapse Raw Protocol) | [01-synapse-raw-protocol.md](./01-synapse-raw-protocol.md) | - | 纲领性文档 | -| A2A 协议 | [02-a2a-protocol.md](./02-a2a-protocol.md) | `a2a` | `sdk/a2a/` | -| A2N 协议 | [03-a2n-protocol.md](./03-a2n-protocol.md) | `a2n` | `sdk/a2n/` | -| P2A 协议 | [04-p2a-protocol.md](./04-p2a-protocol.md) | `p2a` | `sdk/p2a/` | - -**所有协议版本:1.0.0** - ---- - -## 9. 扩展建议 - -| 优先级 | 扩展项 | 说明 | -|-------|-------|------| -| 高 | gRPC 传输 | 添加 gRPC 协议支持 | -| 高 | WebSocket | 添加 WebSocket 流式传输 | -| 中 | 批量操作 | 批量任务提交、批量查询 | -| 中 | 指标监控 | 内置指标收集 | -| 低 | 多语言 SDK | Python、JavaScript 等 | - ---- - -## 附录:相关文件索引 - -| 文件路径 | 说明 | -|---------|------| -| [sdk/doc.go](../sdk/doc.go) | SDK 包文档 | -| [sdk/p2a/client.go](../sdk/p2a/client.go) | P2A 客户端实现 | -| [sdk/a2a/client.go](../sdk/a2a/client.go) | A2A 客户端实现 | -| [sdk/a2n/client.go](../sdk/a2n/client.go) | A2N 客户端实现 | -| [externalapi/handler.go](../externalapi/handler.go) | P2A 协议服务端实现 | -| [p2p/protocol.go](../p2p/protocol.go) | A2A 协议核心实现 | -| [group/protocol.go](../group/protocol.go) | A2N 协议核心实现 | -| [types/types.go](../types/types.go) | 公共类型定义 | -| [transport/transport.go](../transport/transport.go) | HTTP 传输层实现 | diff --git a/synapse/docs/06-solutions-whitepaper.md b/synapse/docs/06-solutions-whitepaper.md deleted file mode 100644 index 0f58f3d..0000000 --- a/synapse/docs/06-solutions-whitepaper.md +++ /dev/null @@ -1,777 +0,0 @@ -# 灵隙协议族(Synapse Protocol Suite) - 解决方案白皮书 - -> 版本:1.0.0 -> 日期:2026-06-27 -> 状态:草案 -> 前置阅读:[灵隙原始协议(Synapse Raw Protocol)](./01-synapse-raw-protocol.md) - ---- - -## 目录 - -1. [概述](#1-概述) -2. [方案一:Agent 发现与广播机制](#2-方案一agent-发现与广播机制) -3. [方案二:身份认证与信任体系](#3-方案二身份认证与信任体系) -4. [方案三:协议缺失内容补全](#4-方案三协议缺失内容补全) -5. [分阶段实施路线图](#5-分阶段实施路线图) -6. [技术选型建议](#6-技术选型建议) - ---- - -## 1. 概述 - -### 1.1 背景 - -当前灵隙协议族(Synapse Protocol Suite)定义了 Agent 之间"怎么说话"(消息格式、任务流程),但缺少: - -- **怎么找到对方** — Agent 发现与广播机制 -- **怎么相信对方** — 身份认证与信任体系 -- **怎么规模化协作** — 路由、调度、激励等基础设施 - -本文档针对上述问题给出完整的解决方案。 - -### 1.2 设计原则 - -| 原则 | 说明 | -|------|------| -| **渐进式** | 从简单到复杂,每阶段都可用 | -| **可插拔** | 组件可替换,不绑定具体实现 | -| **传输无关** | 不依赖特定底层网络 | -| **安全优先** | 身份认证是基础设施,不是可选功能 | -| **向后兼容** | 不破坏现有协议,增量扩展 | - ---- - -## 2. 方案一:Agent 发现与广播机制 - -### 2.1 整体架构 - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Agent 发现与广播层 │ -├─────────────────────┬─────────────────────┬─────────────────────────┤ -│ 集中式目录服务 │ 分布式 Gossip │ 组播/广播 │ -│ (Directory) │ (Gossip) │ (Multicast) │ -│ ┌───────────────┐ │ ┌───────────────┐ │ ┌────────────────┐ │ -│ │ 注册/注销 │ │ │ 消息泛洪 │ │ │ 子网内广播 │ │ -│ │ 能力索引 │ │ │ 状态同步 │ │ │ 邻居发现 │ │ -│ │ 名字解析 │ │ │ 节点发现 │ │ │ 本地心跳 │ │ -│ └───────────────┘ │ └───────────────┘ │ └────────────────┘ │ -└─────────────────────┴─────────────────────┴─────────────────────────┘ -``` - -### 2.2 模式一:集中式目录服务(推荐首选) - -#### 2.2.1 架构说明 - -引入 **Agent Directory Service(ADS)** 作为中心化的 Agent 目录服务,类似 DNS。 - -``` -Agent A ──注册──▶ ┌─────────────┐ ◀──注册── Agent B - │ Directory │ -Agent C ──查询──▶ │ Service │ ◀──心跳── Agent D - └─────────────┘ - │ - ▼ - 能力索引 - 在线状态 - 端点地址 -``` - -#### 2.2.2 核心接口 - -**注册协议(Agent → Directory):** - -| 操作 | 消息类型 | 说明 | -|------|---------|------| -| 注册 | `dir:register` | Agent 上线时注册自身信息 | -| 注销 | `dir:unregister` | Agent 下线时注销 | -| 心跳 | `dir:heartbeat` | 定期上报存活状态 | -| 更新能力 | `dir:update_capabilities` | 能力变化时更新 | - -**查询协议(Agent → Directory):** - -| 操作 | 消息类型 | 说明 | -|------|---------|------| -| 按 ID 查询 | `dir:query_by_id` | 根据 AgentID 查端点 | -| 按能力查询 | `dir:query_by_capability` | 找具备某能力的 Agent | -| 列表查询 | `dir:list` | 分页列出所有 Agent | -| 批量查询 | `dir:batch_query` | 批量查询多个 Agent | - -#### 2.2.3 注册数据结构 - -```json -{ - "agent_id": "agent-001", - "agent_name": "视频生成Agent", - "system_id": "video-system", - "endpoint": "https://agent-001.example.com/synapse/callback", - "version": "1.0.0", - "capabilities": [ - { - "type": "video_generation", - "name": "视频生成", - "description": "根据脚本生成视频", - "max_concurrent": 10, - "avg_latency_ms": 5000 - } - ], - "transports": ["http", "grpc"], - "status": "online", - "last_heartbeat": "2026-06-27T10:00:00Z", - "trust_score": 85, - "public_key": "-----BEGIN PUBLIC KEY-----\n..." -} -``` - -#### 2.2.4 优缺点 - -| 优点 | 缺点 | -|------|------| -| 查询效率高(O(1)) | 单点故障风险 | -| 支持复杂查询(按能力、按系统等) | 中心节点需信任 | -| 易于管理和监控 | 扩展性有上限 | -| 实现简单 | 存在注册/注销时序问题 | - ---- - -### 2.3 模式二:分布式 Gossip 协议(可选扩展) - -#### 2.3.1 架构说明 - -无中心节点,Agent 之间通过 Gossip 协议(epidemic protocol)扩散状态信息,类似比特币网络的节点发现。 - -``` -Agent A ──gossip──▶ Agent B ──gossip──▶ Agent D - │ │ - └──gossip──▶ Agent C ──gossip──▶ Agent E -``` - -#### 2.3.2 核心机制 - -| 机制 | 说明 | -|------|------| -| **Peer Sampling** | 每个 Agent 维护一个部分视图(partial view) | -| **Active Push** | 定期随机选几个节点推送本地状态 | -| **Passive Pull** | 收到推送后,有概率回传自身状态 | -| **TTL** | 消息有存活跳数,防止无限扩散 | -| **Deduplication** | 消息 ID 去重,避免重复处理 | - -#### 2.3.3 Gossip 消息格式 - -```json -{ - "type": "gossip:state", - "from": "agent-001", - "view": [ - {"agent_id": "agent-002", "endpoint": "...", "capabilities": [...], "timestamp": "..."}, - {"agent_id": "agent-003", "endpoint": "...", "capabilities": [...], "timestamp": "..."}, - {"agent_id": "agent-004", "endpoint": "...", "capabilities": [...], "timestamp": "..."} - ], - "ttl": 5, - "msg_id": "msg-xxx" -} -``` - -#### 2.3.4 优缺点 - -| 优点 | 缺点 | -|------|------| -| 完全去中心化 | 查询效率低(需本地构建视图) | -| 容错性强 | 状态最终一致,有延迟 | -| 可无限扩展 | 实现复杂度高 | -| 无单点故障 | 网络流量大 | - ---- - -### 2.4 模式三:本地组播/邻居发现(局域网场景) - -适用于同一内网/集群内的 Agent 快速发现。 - -#### 2.4.1 机制 - -| 机制 | 说明 | -|------|------| -| **UDP 组播** | 定期在组播地址发送广播 | -| **mDNS/DNS-SD** | 类似 Apple Bonjour 的服务发现 | -| **ARP/NDP** | 链路层发现(不推荐) | - -#### 2.4.2 适用场景 - -- 边缘计算集群 -- 同一机房内的 Agent 集群 -- 本地开发测试环境 - ---- - -### 2.5 广播机制设计 - -#### 2.5.1 广播类型 - -| 广播范围 | 消息类型前缀 | 说明 | -|---------|-------------|------| -| 全网广播 | `global:` | 所有在线 Agent | -| 系统广播 | `system:` | 同一 system_id 内 | -| 群组广播 | `group:` | 同一群组内(已有) | -| 能力组广播 | `cap:` | 具备某能力的 Agent | - -#### 2.5.2 广播实现 - -**集中式模式下:** -- 由 Directory Service 转发广播消息 -- 支持按条件过滤(按能力、按系统等) - -**分布式模式下:** -- 通过 Gossip 协议泛洪 -- TTL 控制扩散范围 -- 消息 ID 去重 - ---- - -### 2.6 心跳与存活检测 - -#### 2.6.1 心跳机制 - -``` -Agent ───heartbeat──▶ Directory - (每30秒) - -Directory 判定离线: - - 连续 3 次未收到心跳 → 标记为 offline - - 离线 24 小时 → 自动注销 -``` - -#### 2.6.2 主动探测 - -``` -Directory ───ping──▶ Agent - ◀──pong── -``` - -用于验证 Agent 是否真的在线(防止心跳伪造)。 - ---- - -## 3. 方案二:身份认证与信任体系 - -### 3.1 三层身份架构 - -``` -┌─────────────────────────────────────────────────┐ -│ Layer 3: 信任评分 (Trust Score) │ -│ 声誉系统、历史行为、第三方评价 │ -├─────────────────────────────────────────────────┤ -│ Layer 2: 身份验证 (Authentication) │ -│ 签名验证、证书校验、DID 验证 │ -├─────────────────────────────────────────────────┤ -│ Layer 1: 身份标识 (Identity) │ -│ AgentID + 公钥 / 证书 / DID │ -└─────────────────────────────────────────────────┘ -``` - -### 3.2 Layer 1:身份标识方案 - -#### 3.2.1 方案 A:公钥身份(推荐基础版) - -**核心思想**:AgentID = 公钥哈希(类似比特币地址) - -``` -AgentID = base58(sha256(public_key)[:20]) -例:agent-1A2B3C4D5E6F... -``` - -**优点:** -- 自包含,不需要中心 CA -- 公钥可验证身份 -- 实现简单 - -**缺点:** -- 身份无法撤销(私钥泄露 = 身份被盗) -- 没有人类可读的名字 -- 无法关联真实世界身份 - -**适用场景**:内部系统、测试环境、信任度要求不高的场景 - -#### 3.2.2 方案 B:PKI 证书体系 - -**核心思想**:引入 CA(Certificate Authority)颁发证书 - -``` -CA 根证书 - ├── 系统A证书 - │ ├── Agent-001 证书 - │ └── Agent-002 证书 - └── 系统B证书 - └── Agent-003 证书 -``` - -**优点:** -- 成熟的工业标准 -- 支持证书撤销(CRL/OCSP) -- 有层级信任关系 - -**缺点:** -- 需要信任中心化 CA -- 证书管理复杂 -- 跨 CA 互操作需要桥接 - -**适用场景**:企业内部、有明确信任中心的场景 - -#### 3.2.3 方案 C:区块链 DID(去中心化身份) - -**核心思想**:身份上链,链上存公钥和属性,类似 W3C DID 标准。 - -``` -链上存储: - DID → { - "publicKey": "...", - "controller": "...", - "authentication": [...], - "service": [...], - "revoked": false, - "timestamp": "..." - } -``` - -**三种实现路径:** - -| 路径 | 说明 | 适用场景 | -|------|------|---------| -| **公链 DID** | 使用以太坊/Solana 等公链 | 开放生态、跨组织协作 | -| **联盟链 DID** | 多机构共建联盟链 | 行业联盟、政企合作 | -| **私有链 DID** | 单组织内部链 | 企业内部、对性能要求高 | - -**优点:** -- 去中心化,无单点故障 -- 身份可验证、可追溯 -- 支持跨系统互认 -- 不可篡改的身份历史 - -**缺点:** -- 链上操作有延迟 -- 需要支付 Gas 费(公链) -- 实现复杂度高 -- 隐私保护需额外设计 - ---- - -### 3.3 Layer 2:身份验证方案 - -#### 3.3.1 消息签名验证 - -所有灵隙消息必须签名,签名方式: - -``` -签名内容 = SHA256(message_id + sender + receiver + payload + timestamp) -签名 = Sign(private_key, 签名内容) -验证 = Verify(public_key, 签名内容, 签名) -``` - -#### 3.3.2 签名放置位置 - -| 位置 | 说明 | -|------|------| -| 消息体内 | `signature` 字段 | -| HTTP Header | `X-Synapse-Signature` | -| gRPC Metadata | `x-synapse-signature` | - -#### 3.3.3 防重放攻击 - -``` -每个消息有唯一 message_id + timestamp -接收方维护已处理 message_id 缓存(如最近 1 小时) -timestamp 与本地时间差超过 5 分钟 → 拒绝 -``` - ---- - -### 3.4 Layer 3:信任评分体系 - -#### 3.4.1 信任分维度 - -| 维度 | 权重 | 说明 | -|------|------|------| -| 任务完成率 | 30% | 历史任务成功 / 总任务数 | -| 任务质量 | 25% | 结果评分、返工率 | -| 响应速度 | 15% | 平均响应时间 | -| 在线稳定性 | 15% | 在线时长 / 总时长 | -| 历史信誉 | 15% | 其他 Agent 的评价 | - -#### 3.4.2 信任分计算 - -``` -trust_score = Σ(维度_i × 权重_i) - -范围:0 - 100 -等级: - 90-100 S 级 高度可信 - 75-89 A 级 可信 - 60-74 B 级 一般可信 - 40-59 C 级 谨慎使用 - 0-39 D 级 不可信 -``` - -#### 3.4.3 信任传递 - -``` -A 信任 B(评分 90) -B 信任 C(评分 85) -A 对 C 的初始信任 = 90 × 85% × 衰减因子 = 约 68 -``` - -**注意**:信任传递有衰减,防止信任污染。 - ---- - -### 3.5 区块链适用性决策树 - -``` -是否需要跨组织协作? -├── 否 → 用 PKI 或公钥身份(简单高效) -└── 是 → 是否有共同信任的中心机构? - ├── 是 → 用 PKI 体系(成熟可靠) - └── 否 → 是否需要不可篡改的审计? - ├── 是 → 考虑联盟链 DID - └── 否 → 公钥身份 + 声誉系统可能够用 -``` - ---- - -## 4. 方案三:协议缺失内容补全 - -### 4.1 第一优先级补全(核心基础设施) - -#### 4.1.1 Agent 发现协议(ADS - Agent Discovery Service) - -**新增消息类型:** - -| 消息类型 | 方向 | 说明 | -|---------|------|------| -| `dir:register` | Agent → Directory | 注册 Agent | -| `dir:unregister` | Agent → Directory | 注销 Agent | -| `dir:heartbeat` | Agent → Directory | 心跳 | -| `dir:update_capabilities` | Agent → Directory | 更新能力 | -| `dir:query_by_id` | Agent → Directory | 按 ID 查询 | -| `dir:query_by_capability` | Agent → Directory | 按能力查询 | -| `dir:list` | Agent → Directory | 列表查询 | -| `dir:query_result` | Directory → Agent | 查询结果 | - -**新增数据结构:** `AgentDirectoryEntry`, `CapabilityIndex`, `QueryFilter` - -#### 4.1.2 身份认证规范 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `auth:challenge` | 身份挑战 | -| `auth:response` | 挑战响应 | -| `auth:cert_exchange` | 证书交换 | - -**新增内容:** -- 标准签名算法列表(Ed25519, ECDSA P-256, RSA 2048) -- 消息签名格式规范 -- 防重放攻击机制 -- 身份验证流程规范 - -#### 4.1.3 心跳与存活检测 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `net:ping` | 存活探测 | -| `net:pong` | 存活响应 | -| `net:offline_notify` | 下线通知 | - -**规范内容:** -- 心跳间隔(默认 30 秒) -- 超时判定(连续 3 次未收到 → 离线) -- 离线通知机制 - -#### 4.1.4 统一错误码体系 - -**错误分类:** - -| 错误码前缀 | 类别 | 示例 | -|-----------|------|------| -| `msg_` | 消息层 | msg_invalid_format, msg_signature_invalid | -| `auth_` | 认证层 | auth_failed, auth_expired, auth_forbidden | -| `task_` | 任务层 | task_not_found, task_timeout, task_cancelled | -| `cap_` | 能力层 | cap_lacking, cap_busy, cap_not_supported | -| `group_` | 群组层 | group_not_found, group_full, group_permission_denied | -| `dir_` | 目录层 | dir_agent_not_found, dir_query_failed | -| `net_` | 网络层 | net_timeout, net_offline, net_unreachable | -| `sys_` | 系统层 | sys_internal_error, sys_not_implemented | - ---- - -### 4.2 第二优先级补全(重要功能) - -#### 4.2.1 能力匹配与任务路由 - -**功能:** -- 智能选择最合适的 Agent 执行任务 -- 支持负载均衡(按并发数、响应速度、信任分) -- 支持任务失败自动重试/转发 - -**新增消息类型:** -- `router:submit_task` - 提交给路由器自动选择执行者 -- `router:forward` - 任务转发 - -#### 4.2.2 全网广播协议 - -**新增消息类型:** - -| 消息类型 | 说明 | -|---------|------| -| `global:broadcast` | 全网广播 | -| `system:broadcast` | 系统内广播 | -| `cap:broadcast` | 能力组广播 | - -**规范内容:** -- 广播范围定义 -- TTL 与去重机制 -- 广播风暴防护 - -#### 4.2.3 版本协商机制 - -**功能:** -- Agent 之间协商使用的协议版本 -- 向后兼容处理 -- 能力降级策略 - -**新增消息类型:** -- `meta:version_query` - 查询支持的版本 -- `meta:version_negotiate` - 版本协商 - -#### 4.2.4 幂等性保证 - -**规范内容:** -- 幂等键(Idempotency Key)机制 -- 重复消息处理规范 -- 任务级幂等 vs 消息级幂等 - ---- - -### 4.3 第三优先级补全(增强功能) - -#### 4.3.1 流式输出协议 - -**功能:** -- 长任务实时进度推送 -- 生成式 AI 的 token 流式输出 -- WebSocket/SSE 传输支持 - -#### 4.3.2 批量任务协议 - -**功能:** -- 一次性提交多个同类型任务 -- 批量状态查询 -- 批量结果收集 - -#### 4.3.3 支付与激励机制 - -**功能:** -- 任务定价与结算 -- Token 或积分系统 -- 智能合约自动结算(区块链场景) - -#### 4.3.4 群组发现协议 - -**功能:** -- 按主题/任务类型查找群组 -- 推荐加入合适的群组 -- 群组热度/活跃度排名 - ---- - -### 4.4 安全相关补全 - -#### 4.4.1 端到端加密 - -**规范内容:** -- 密钥协商(ECDH) -- 对称加密载荷(AES-GCM) -- 前向保密(PFS) - -#### 4.4.2 权限委托 - -**功能:** -- Agent A 委托 Agent B 代表自己执行任务 -- 委托令牌(Delegation Token) -- 委托范围与时效控制 - -#### 4.4.3 审计日志标准 - -**规范内容:** -- 统一审计日志格式 -- 关键操作必须记录 -- 日志完整性保护(哈希链) - ---- - -## 5. 分阶段实施路线图 - -### 5.1 Phase 0:基础版(MVP) - 预计 2 周 - -**目标**:协议可用,能跑通基本流程 - -**内容:** -- [x] 灵隙点对点任务协议(已完成) -- [x] A2N 群组协作协议(已完成) -- [x] P2A 外部调用协议(已完成) -- [x] 三套协议的 SDK 实现(已完成) - ---- - -### 5.2 Phase 1:发现与身份 - 预计 4 周 - -**目标**:Agent 能互相找到对方,能验证对方身份 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| Agent 目录服务协议 | 集中式 ADS | P0 | -| 公钥身份规范 | Ed25519 签名验证 | P0 | -| 心跳与存活检测 | 30 秒心跳,3 次超时判定离线 | P0 | -| 统一错误码体系 | 8 大类错误码 | P0 | -| 防重放攻击 | message_id + timestamp | P0 | - -**输出物:** -- 新协议文档:`06-agent-discovery.md` -- 新协议文档:`07-authentication.md` -- 代码:`discovery/` 包(目录服务客户端) -- 代码:`auth/` 包(签名验证工具) -- 更新 types 包:新增消息类型和错误码 - ---- - -### 5.3 Phase 2:路由与广播 - 预计 4 周 - -**目标**:支持智能任务路由和全网广播 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 任务路由协议 | 按能力 + 负载 + 信任分选择执行者 | P1 | -| 全网广播协议 | 基于目录服务的广播转发 | P1 | -| 版本协商机制 | 协议版本兼容 | P1 | -| 幂等性保证 | 幂等键 + 去重 | P1 | - -**输出物:** -- 新协议文档:`08-routing-and-broadcast.md` -- 代码:`routing/` 包增强(增加能力路由) -- 更新目录服务:支持广播转发 - ---- - -### 5.4 Phase 3:信任与激励 - 预计 6 周 - -**目标**:建立信任体系,支持规模化协作 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 信任评分体系 | 5 维度信任分计算 | P2 | -| 流式输出协议 | WebSocket/SSE 流式进度 | P2 | -| 批量任务协议 | 批量提交/查询/收集 | P2 | -| 群组发现协议 | 群组搜索与推荐 | P2 | -| SLA 协议 | 服务等级承诺 | P3 | - -**输出物:** -- 新协议文档:`09-trust-and-reputation.md` -- 代码:`trust/` 包(信任评分引擎) - ---- - -### 5.5 Phase 4:高级特性 - 预计 8 周+ - -**目标**:企业级、生产级完整功能 - -**新增协议模块:** - -| 模块 | 说明 | 优先级 | -|------|------|--------| -| 端到端加密 | ECDH + AES-GCM | P3 | -| 权限委托 | 委托令牌机制 | P3 | -| 支付与激励 | Token/积分系统 | P3 | -| 区块链 DID 集成 | 可选模块 | P4 | -| 审计日志标准 | 统一审计格式 | P3 | -| Gossip 协议 | 分布式发现(可选) | P4 | - ---- - -## 6. 技术选型建议 - -### 6.1 目录服务存储选型 - -| 方案 | 适用场景 | 优点 | 缺点 | -|------|---------|------|------| -| **Redis** | 中小规模 | 高性能,支持 TTL | 数据量受限 | -| **PostgreSQL** | 中大规模 | 复杂查询,持久化 | 需运维 | -| **Elasticsearch** | 大规模 + 全文检索 | 强大的搜索能力 | 运维复杂 | - -**推荐**:先用 Redis(简单快),规模大了再迁 PostgreSQL。 - ---- - -### 6.2 签名算法选型 - -| 算法 | 安全性 | 性能 | 密钥长度 | 推荐度 | -|------|--------|------|---------|--------| -| Ed25519 | 高 | 快 | 256 位 | ⭐⭐⭐⭐⭐ 首选 | -| ECDSA P-256 | 高 | 中 | 256 位 | ⭐⭐⭐⭐ 兼容 | -| RSA 2048 | 中 | 慢 | 2048 位 | ⭐⭐ 仅兼容 | - -**推荐**:默认 Ed25519,需要兼容旧系统时支持 ECDSA。 - ---- - -### 6.3 区块链选型(如果需要) - -| 场景 | 推荐方案 | 说明 | -|------|---------|------| -| 企业内部 | **私有链(Hyperledger Fabric)** | 可控,高性能,无 Gas 费 | -| 行业联盟 | **联盟链(FISCO BCOS / ChainMaker)** | 多机构共建,合规 | -| 开放生态 | **公链(以太坊 / Solana)** | 完全开放,需 Gas 费 | -| 简单原型 | **模拟链(数据库模拟)** | 先验证逻辑,再上真链 | - -**推荐**:90% 的场景用不到真区块链,先用数据库模拟验证业务逻辑。 - ---- - -## 7. 总结与建议 - -### 7.1 核心建议 - -1. **先集中后分布**:先用集中式目录服务,简单高效;规模大了再考虑分布式 -2. **先公钥后区块链**:先用公钥身份解决 80% 的问题,真的需要了再上链 -3. **先 MVP 后完善**:先跑通核心流程,再逐步加高级功能 -4. **标准接口可替换**:目录服务、身份系统都做成可插拔的,方便未来升级 - -### 7.2 下一步行动 - -| 序号 | 行动 | 负责人 | 产出 | -|------|------|--------|------| -| 1 | 评审本方案,确认 Phase 1 范围 | 架构组 | 确认后的方案 | -| 2 | 设计目录服务 API 详细规范 | 协议组 | `06-agent-discovery.md` | -| 3 | 设计身份认证详细规范 | 协议组 | `07-authentication.md` | -| 4 | 实现目录服务原型 | 开发组 | 可运行的 ADS 服务 | -| 5 | 更新 SDK 支持发现和认证 | 开发组 | 新版 SDK | - ---- - -## 附录:相关文档索引 - -| 文档 | 说明 | -|------|------| -| [01-synapse-raw-protocol.md](./01-synapse-raw-protocol.md) | 灵隙原始协议(Synapse Raw Protocol)(纲领) | -| [02-a2a-protocol.md](./02-a2a-protocol.md) | A2A 协议(P2P 任务) | -| [03-a2n-protocol.md](./03-a2n-protocol.md) | A2N 协议(群组协作) | -| [04-p2a-protocol.md](./04-p2a-protocol.md) | P2A 协议(外部调用) | -| [05-sdk-implementation.md](./05-sdk-implementation.md) | SDK 实现说明 | -| **本文档** | **解决方案白皮书** | diff --git a/types/types.go b/types/types.go index dce3331..43c7aee 100644 --- a/types/types.go +++ b/types/types.go @@ -164,6 +164,18 @@ const ( GroupMemberBusy GroupMemberStatus = "busy" ) +// ============================================================================= +// Signature Algorithm +// ============================================================================= + +// SignatureAlgorithm defines supported signature algorithms +type SignatureAlgorithm string + +const ( + AlgHMACSHA256 SignatureAlgorithm = "HMAC-SHA256" // 默认 + AlgHMACSHA512 SignatureAlgorithm = "HMAC-SHA512" +) + // ============================================================================= // Priority // ============================================================================= @@ -175,6 +187,7 @@ const ( PriorityHigh Priority = "high" PriorityNormal Priority = "normal" PriorityLow Priority = "low" + PriorityUrgent Priority = "urgent" ) // ============================================================================= @@ -213,8 +226,9 @@ type UnifiedSynapseMessage struct { Broadcast bool `json:"broadcast,omitempty"` // Security - Signature string `json:"signature,omitempty"` - Encrypt bool `json:"encrypt,omitempty"` + Signature string `json:"signature,omitempty"` + SignatureAlgorithm string `json:"signature_algorithm,omitempty"` + Encrypt bool `json:"encrypt,omitempty"` // Timestamps Timestamp Timestamp `json:"timestamp"`