灵隙(synapse) v1.0.0 版本

This commit is contained in:
lychang
2026-06-27 22:16:05 +08:00
parent e0025a2563
commit 7b105ded96
23 changed files with 107 additions and 9926 deletions

View File

@@ -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:初始版本,定义核心概念与设计原则

View File

@@ -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能力)

View File

@@ -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能力)

View File

@@ -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` 字段标识群组上下文

View File

@@ -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` 字段标识群组上下文

View File

@@ -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 | 简化验证 |

View File

@@ -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 | 简化验证 |

View File

@@ -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 传输层实现 |

View File

@@ -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 实现说明 |
| **本文档** | **解决方案白皮书** |

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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,
})
}
// =============================================================================
// 回调发送器
// =============================================================================

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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(),
}
}

View File

@@ -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:初始版本,定义核心概念与设计原则

View File

@@ -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能力)

View File

@@ -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` 字段标识群组上下文

View File

@@ -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 | 简化验证 |

View File

@@ -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 传输层实现 |

View File

@@ -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 实现说明 |
| **本文档** | **解决方案白皮书** |

View File

@@ -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"`