Files
agent_management/docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md

709 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent Runtime → Heicode Manager 反向 Callback 契约 v1(提案)
> **状态**:DRAFT — 由 Heicode Manager 团队起草,发回给 Agent Manager 团队评审
> **配套阅读**:`HEICODE_API_INTEGRATION.md`(v2.0.0,正向:Heicode → Agent Manager)
> **目标版本**:v1.0
> **草案日期**:2026-05-26
> **联系人**:Heicode Manager 团队
---
## 0. 摘要(给评审同事 30 秒看懂)
`HEICODE_API_INTEGRATION.md` 描述了 **Heicode → Agent Manager** 的正向调用(创建部署 / 拉日志 / 拉事件)。但 **Agent Manager → Heicode** 的反向通知协议**没有定义**,导致 Heicode 这边只能轮询,无法实时知道:
1. 部署进到哪一个标准阶段(需求 / 设计 / 后端 / 前端 / 检查 / 测试 / 部署)
2. Agent 调用了哪个 SK 工具、产出什么、是否失败
3. 高危操作发起审批请求 + 客户端审批结果回流
4. 预算告警触发
5. Agent / Pod 异常退出
本提案定义一个 **HTTP Webhook + HMAC 签名** 的反向通知协议,覆盖上述 5 类共 **10 个标准事件**。
最小可用版本(v1.0)实施工作量评估:Agent Manager 侧约 1-1.5 周,Heicode Manager 侧约 1 周(接收端可与对方并行)。
---
## 1. 当前对接现状(梳理给评审)
### 1.1 正向(已实现,文档 v2.0.0)
```
Heicode Manager ──POST /api/agent/sub-agile/deployments──▶ Agent Manager
──GET /api/agent/.../logs────▶
──GET /api/agent/.../events──▶
──GET /api/agent/.../metrics─▶
```
### 1.2 反向(**未定义** — 本文要解决的)
```
Heicode Manager ◀──??? Agent Manager 怎么告诉我们:
- 进入了"前端"阶段?
- Agent 刚调了 search_web 工具?
- 这次部署要花 $80 了,超过 80% 阈值?
- 高危操作等用户审批?
- Agent Pod 被 K8s OOMKilled?
```
**当前只能靠 Heicode 这边轮询 `/events`**,1 分钟轮询一次 = 用户最坏要等 1 分钟才看到状态变化,且浪费请求。
---
## 2. 协议总览
```
┌──────────────────┐ ┌────────────────────┐
│ Heicode Manager │ │ Agent Manager │
│ (生产环境位于 │ │ (deploys 子环境) │
│ code.xinghanlab │ │ │
│ .com) │ │ │
│ │ │ │
│ ① 创建部署时注册│ ──── POST /deployments──▶│ │
│ callback_url │ body 带 callback_url│ │
│ │ │ │
│ │ │ ② 子环节切换 / │
│ │ │ SK 调用 / │
│ │ │ 审批等事件触发 │
│ │ │ │
│ ③ 接收回调 │ ◀──POST {callback_url}───│ │
│ /api/agent │ 含 HMAC 签名 + │ │
│ /callback │ X-Agnet-Event-Id 幂等 │ │
│ │ │ │
│ ④ 200 OK 回执 │ ────────────────────────▶│ │
│ │ │ │
│ 非 200 → 退避重试│ ◀──────────────────────│ 按重试策略最多 5 次 │
└──────────────────┘ └────────────────────┘
```
---
## 3. Heicode 侧注册(callback_url 怎么告诉 Agent Runtime)
### 3.1 创建部署时携带
扩展 `POST /api/agent/sub-agile/deployments` 请求体,新增可选字段:
```json
{
"orchestration_plan": "...",
"agents": [ ... ],
"callback": {
"url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events",
"signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key",
"subscribed_events": [
"phase.changed",
"sk_tool.called",
"sk_tool.completed",
"sk_tool.failed",
"approval.requested",
"approval.granted",
"approval.rejected",
"budget.alert",
"deployment.status_changed",
"agent.crashed"
]
}
}
```
- `url`:Heicode 接收端点;**必须 HTTPS**
- `signing_secret_ref`:HMAC 签名密钥的 Vault 引用(**不传明文**)
- `subscribed_events`:可选,省略则推送全部;后续允许只订阅子集
### 3.2 后绑定 / 修改(可选 P2 阶段)
```
PATCH /api/agent/sub-agile/deployments/{deployment_id}/callback
```
允许在部署运行期间更换 callback URL(例如 Heicode 灰度发布切换接收端)。
---
## 4. Callback 接收接口(核心)
### 4.1 Endpoint
| 方法 | URL | 说明 |
|------|-----|------|
| `POST` | `{callback_url}` | Agent Runtime 推送事件 |
Heicode 生产端点(建议):
```
POST https://code.xinghanlab.com/api/agent/callbacks/runtime-events
```
### 4.2 必需 Headers
| Header | 必需 | 说明 |
|--------|------|------|
| `Content-Type` | ✅ | 固定 `application/json; charset=utf-8` |
| `X-Agnet-Event-Id` | ✅ | UUID v4。**幂等去重 key**,Heicode 端基于此判重 |
| `X-Agnet-Event-Type` | ✅ | 事件类型短码(见 §5),冗余字段方便日志快速过滤 |
| `X-Agnet-Deployment-Id` | ✅ | 关联的部署 ID |
| `X-Agnet-Timestamp` | ✅ | 事件发生时刻(unix-ms) |
| `X-Agnet-Signature` | ✅ | HMAC-SHA256 签名(见 §4.3) |
| `X-Agnet-Signature-Version` | ✅ | 固定 `v1`,方便未来切换 |
| `X-Agnet-Delivery-Id` | ✅ | 本次投递的 UUID(同事件重试时 event_id 不变、delivery_id 变) |
| `X-Agnet-Delivery-Attempt` | ✅ | 投递尝试次数,1-base。首次=1,重试=2/3/4/5 |
### 4.3 HMAC 签名规范
**为什么需要签名**:Heicode 的 callback endpoint 必须能被公网访问(Agnet 跨网络推过来),如果不签名,任何人都能伪造事件骗 Heicode 改状态。
**签名算法**:
```
canonical_string = X-Agnet-Event-Id + "\n"
+ X-Agnet-Event-Type + "\n"
+ X-Agnet-Deployment-Id + "\n"
+ X-Agnet-Timestamp + "\n"
+ X-Agnet-Delivery-Id + "\n"
+ X-Agnet-Delivery-Attempt + "\n"
+ sha256_hex(request_body)
signature = base64( HMAC-SHA256(signing_secret, canonical_string) )
```
**Heicode 侧校验顺序**(务必按此顺序,先廉价后昂贵):
1. 检查 `X-Agnet-Timestamp` 在当前时间 ±5 分钟内 → 防回放
2. 检查 `X-Agnet-Event-Id` 不在最近 24h 已处理列表 → 幂等去重
3. 计算 canonical_string → 比对 `X-Agnet-Signature` → 验真
4. 解析 body → 校验事件结构 → 分发处理
**密钥管理**:
- 签名密钥由 Heicode 端**生成**并写入 Vault
- 创建部署时 Heicode 把 vault 引用(`signing_secret_ref`)传给 Agent Manager
- Agent Manager 从 Vault 取出 → 签名 → 立刻丢弃,不长期持有
### 4.4 幂等性约定
Heicode 端必须:
- 用 `X-Agnet-Event-Id` 作为去重 key(Redis SETNX,TTL 24h)
- 同一 `event_id` 第 2 次到达 → **返回 200 OK** + 不重复处理(不是 409,避免 Agnet 误判失败再重试)
- 响应头返回 `X-Heicode-Event-Status: duplicate` 让 Agnet 知道已收过
### 4.5 重试策略
Agent Manager 端**必须**实现:
| 触发条件 | 策略 |
|----------|------|
| 收到 2xx | 投递成功,结束 |
| 收到 4xx(除 408 / 429) | **不重试** — 签名错 / 体格式错等是协议错,重试也没用,记 dead letter |
| 收到 408 / 429 / 5xx 或网络超时 | 重试 |
| 重试间隔 | 指数退避:5s, 30s, 2min, 10min, 30min |
| 最大尝试次数 | 5 次(首发 + 4 次重试) |
| 全部失败后 | 写 dead letter queue + 发告警,可由人工触发 replay |
### 4.6 响应格式
**成功**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
X-Heicode-Event-Status: accepted | duplicate
{ "success": true }
```
**Heicode 端临时性错误(要 Agnet 重试)**:
```http
HTTP/1.1 503 Service Unavailable
{
"success": false,
"error": { "code": "DOWNSTREAM_DB_UNAVAILABLE", "retryable": true }
}
```
**协议永久错误(不重试)**:
```http
HTTP/1.1 400 Bad Request
{
"success": false,
"error": { "code": "SIGNATURE_INVALID", "retryable": false }
}
```
---
## 5. 事件类型清单(v1 必须实现 10 个)
### 5.1 `phase.changed` — 部署阶段切换
**业务价值**:解锁 Heicode Manager 任务详情页的 7 阶段实时进度条(产品文档 M10)。
**触发时机**:Agent Manager 检测到部署整体进入新阶段。
**payload**:
```json
{
"event_type": "phase.changed",
"event_id": "evt_a1b2c3d4...",
"deployment_id": "dep_a1b2c3d4",
"occurred_at": "2026-05-25T10:30:00Z",
"data": {
"from_phase": "requirements",
"to_phase": "design",
"agent_instance_id": null,
"summary": "Requirements gathering complete, moving to design"
}
}
```
**`phase` 必须是以下 7 个标准值之一**(v1 闭集):
| phase | 中文 | 说明 |
|-------|------|------|
| `requirements` | 需求 | 产品 Agent 在澄清目标 |
| `design` | 设计 | 架构 Agent 在出原型 / 设计方案 |
| `backend` | 后端 | 后端 Agent 在写服务端代码 |
| `frontend` | 前端 | 前端 Agent 在写 UI |
| `review` | 检查 | Reviewer Agent 在审代码 |
| `test` | 测试 | 跑测试套件 |
| `deploy` | 部署 | Ops Agent 在部署 / 高危审批中 |
**特殊值**:
- `from_phase` 可为 `null`(首次进入,即从无到 requirements)
- `to_phase` 不可为 `null`
---
### 5.2 `sk_tool.called` — SK 工具被调用
**业务价值**:解锁 Heicode 任务详情页的"Agent 调用了 search_web 工具"实时展示(产品文档 M11)。
**触发时机**:某个 Agent 实例开始调用一个 SK 工具,**调用前**推。
**payload**:
```json
{
"event_type": "sk_tool.called",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:30:15Z",
"data": {
"agent_instance_id": "agi_123abc",
"agent_role": "researcher",
"tool_name": "search_web",
"tool_invocation_id": "inv_xyz789",
"input_summary": "query: 'kubernetes operator best practices' (full args redacted)",
"input_size_bytes": 142,
"sk_source_ref": "git:heicode-tools@v1.2.0/search_web.py"
}
}
```
**安全**:`input_summary` 是 Agent Manager 自己截断的人类可读摘要,**不能包含密钥 / token / 数据库连接串等敏感原文**。Heicode 端只展示 `input_summary`,永不展示完整 args。
---
### 5.3 `sk_tool.completed` — SK 工具调用成功
**触发时机**:工具返回成功结果时。
**payload**:
```json
{
"event_type": "sk_tool.completed",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:30:18Z",
"data": {
"agent_instance_id": "agi_123abc",
"tool_invocation_id": "inv_xyz789",
"duration_ms": 2814,
"output_summary": "10 results returned, top-3 about CRDs and reconcile loops",
"output_size_bytes": 8421,
"cost_usd": 0.0034
}
}
```
`tool_invocation_id` 与 5.2 配对,Heicode 端 join 起来形成"开始-完成-耗时"链。
---
### 5.4 `sk_tool.failed` — SK 工具调用失败
**触发时机**:工具抛异常 / 超时 / 返回错误码。
**payload**:
```json
{
"event_type": "sk_tool.failed",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:30:18Z",
"data": {
"agent_instance_id": "agi_123abc",
"tool_invocation_id": "inv_xyz789",
"duration_ms": 30000,
"failure_code": "TOOL_TIMEOUT",
"failure_message": "search_web exceeded 30s timeout",
"is_recoverable": true,
"retry_count": 2
}
}
```
`failure_code` 建议枚举(不强制):
- `TOOL_TIMEOUT`
- `TOOL_AUTH_FAILED`
- `TOOL_QUOTA_EXCEEDED`
- `TOOL_INPUT_INVALID`
- `TOOL_INTERNAL_ERROR`
- `TOOL_NETWORK`
- `TOOL_UNKNOWN`
---
### 5.5 `approval.requested` — 高危操作请求审批
**业务价值**:解锁产品文档要求的"高危操作必须客户端审批"闭环。
**触发时机**:Agent Manager 遇到 risk_level=high 的具体动作(生产部署、DB 写、删云资源、访问生产密钥等),**暂停执行**,向 Heicode 请求审批。
**payload**:
```json
{
"event_type": "approval.requested",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:35:00Z",
"data": {
"approval_id": "apv_abc123",
"agent_instance_id": "agi_456def",
"operation": "production_deploy",
"target_resource": "azkv://heicode-kv.vault.azure.net/secrets/aks-cluster-prod",
"risk_level": "high",
"human_readable_description": "Deploy commit 7a3f9c to production AKS cluster (replaces 2 running pods)",
"auto_deny_at": "2026-05-25T11:35:00Z",
"blocking": true
}
}
```
- `approval_id`:Heicode 后续审批回调要带这个 ID 让 Agnet 知道针对哪次
- `auto_deny_at`:超过这个时间还没审批 → Agent Manager 自动拒绝并失败
- `blocking=true`:Agent Manager 已暂停部署,等审批
**Heicode 拿到这个事件后做什么**:
1. 推到桌面客户端的审批 UI(已有契约)
2. 用户点同意 / 拒绝
3. Heicode 调正向接口:`POST /api/agent/sub-agile/deployments/{id}/approvals/{approval_id}` body `{ "decision": "granted" | "rejected", "reason": "..." }`
### 5.6 `approval.granted` / 5.7 `approval.rejected`
**触发时机**:Agent Manager 收到 Heicode 的审批决定**之后**,回推一个确认事件(让 Heicode 知道 Agent Manager 已恢复 / 已中止)。
**payload**:
```json
{
"event_type": "approval.granted",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:36:42Z",
"data": {
"approval_id": "apv_abc123",
"decision_by_user_id": "user_42",
"resumed_at": "2026-05-25T10:36:42Z"
}
}
```
`approval.rejected` payload 类似,加 `reason` 字段。
---
### 5.8 `budget.alert` — 预算告警
**触发时机**:累计花费跨过 `alert_threshold_pct`(默认 80%)或硬上限 `max_usd`。
**payload**:
```json
{
"event_type": "budget.alert",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:40:00Z",
"data": {
"alert_level": "warning",
"consumed_usd": 80.5,
"max_usd": 100.0,
"consumed_pct": 80.5,
"threshold_pct": 80,
"projected_overrun": false
}
}
```
`alert_level` 枚举:`warning`(80% 阈值)/ `critical`(≥95%)/ `exceeded`(已超 max_usd,Agent Manager 自动停掉)
---
### 5.9 `deployment.status_changed` — 部署整体状态变更
**业务价值**:替代当前的`/deployments/:id` 轮询,实时通知顶层状态。
**触发时机**:`deployment.status` 字段值变化(pending → running → stopped / failed)。
**payload**:
```json
{
"event_type": "deployment.status_changed",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:30:05Z",
"data": {
"from_status": "pending",
"to_status": "running",
"failure_code": null,
"failure_message": null
}
}
```
stopped / failed 时 `failure_code` / `failure_message` 必填。
---
### 5.10 `agent.crashed` — Agent 异常退出
**触发时机**:单个 Agent Pod 被 K8s 终止(OOM / SIGKILL / 退出码非 0 / liveness probe 失败)。**不包括** Agent 自然完成。
**payload**:
```json
{
"event_type": "agent.crashed",
"event_id": "evt_xxx",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-25T10:42:00Z",
"data": {
"agent_instance_id": "agi_123abc",
"role": "researcher",
"exit_code": 137,
"exit_reason": "OOMKilled",
"restart_count": 2,
"will_restart": true,
"last_log_tail": "MemoryError: out of memory while parsing 4GB JSON",
"uptime_before_crash_sec": 287
}
}
```
`will_restart=true` 时 Agent Manager 自动重启,Heicode 端只是记录;`will_restart=false` 表示重启次数已达上限,部署会进 failed。
---
## 6. 联调 / 沙箱支持(必需)
### 6.1 Mock 事件触发接口(Agent Manager 端实现)
为了让 Heicode 这边在没有真实部署的情况下也能联调 callback 接收逻辑:
```
POST /api/agent/_mock/emit_event
Authorization: Bearer <SERVICE_TOKEN>
{
"callback_url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events",
"event_type": "phase.changed",
"deployment_id": "dep_mock_001",
"data": { "from_phase": null, "to_phase": "requirements" }
}
```
调用后 Agent Manager 立刻按真实流程签名 + POST 一次给 callback_url。
**必须只在 staging / dev 环境暴露**,生产环境 403。
### 6.2 Mock 工具
提供一个 CLI:
```
agnet-cli mock-emit \
--target https://staging.heicode.local/api/agent/callbacks \
--event sk_tool.called \
--deployment dep_mock_001 \
--signing-secret "$(cat /tmp/test-secret)"
```
让两边联调时不依赖真实 Agent 跑起来。
---
## 7. 错误码(Heicode 接收端返回的)
| HTTP 状态码 | error.code | retryable | 说明 |
|------------|------------|-----------|------|
| 200 | — | — | 正常受理 |
| 200 | — | — | 重复(duplicate event_id),返回 200 不让 Agnet 重试 |
| 400 | `SIGNATURE_INVALID` | false | HMAC 验证失败 |
| 400 | `SIGNATURE_VERSION_UNSUPPORTED` | false | 用了我们不支持的签名版本 |
| 400 | `EVENT_BODY_MALFORMED` | false | JSON 解析失败 / 必填字段缺失 |
| 400 | `EVENT_TYPE_UNKNOWN` | false | 不在 §5 枚举里的事件类型 |
| 408 | `RECEIVE_TIMEOUT` | true | Heicode 端 DB 写慢,建议重试 |
| 409 | — | — | 不使用 — 重复 event_id 走 200 路径 |
| 413 | `BODY_TOO_LARGE` | false | 超过 64KB(建议每条事件 < 16KB) |
| 422 | `DEPLOYMENT_NOT_KNOWN` | false | Heicode 这边查不到这个 deployment_id(Agnet 推得太早 / Heicode 还没记录) |
| 429 | `RATE_LIMITED` | true | Heicode 端短期被刷爆 |
| 503 | `DOWNSTREAM_UNAVAILABLE` | true | Heicode 后端 DB / Redis 暂时不可用 |
| 5xx | — | true | 任何 5xx 都按 retryable 处理 |
---
## 8. 时间戳偏移宽容度
由于两侧服务器时钟可能漂移:
- Heicode 端校验 `X-Agnet-Timestamp` 落在 `now ± 5 分钟` 内
- 超出 → 返回 `400 SIGNATURE_INVALID`(防止回放)
- Agent Runtime 端**必须**用 NTP 同步时钟,最大允许偏移 ±60 秒
---
## 9. 事件投递顺序保证(重要)
### 9.1 不保证全局有序
跨不同 deployment_id 的事件**不保证投递顺序**(不同 deployment 在不同 worker 处理)。
### 9.2 同一 deployment 内的事件
**Agent Manager 应尽力按 occurred_at 顺序投递**,但 Heicode 端**不依赖顺序正确**做处理:
- 每个事件自己带 `occurred_at`
- Heicode 按 occurred_at 排序后再展示,不按到达顺序
- 这避免了"重试一个旧 phase.changed 时已经收到新的"导致 phase 倒退
### 9.3 推荐保证级别
| 保证 | v1 提案 |
|------|---------|
| 至少一次(at-least-once)投递 | ✅ 必需 |
| 同 deployment 内顺序 | ⚠️ 尽力 |
| 精确一次(exactly-once)处理 | ✅ 由 Heicode 端用 event_id 幂等保证 |
---
## 10. 实施时间线建议
### Phase 1(**1-1.5 周,可并行**)
**Agent Manager 侧**:
- [ ] 实现 §5 中的 10 个事件触发点
- [ ] 实现 §4.2-4.5 HMAC 签名 + 重试
- [ ] 实现 §6 mock-emit 接口
**Heicode Manager 侧**(不依赖 Agent Manager 完成):
- [ ] 实现 `/api/agent/callbacks/runtime-events` 接收端
- [ ] 实现 §4.3 HMAC 校验、§4.4 幂等去重(复用 Redis SETNX,参考 V2 device-signature nonce 实现)
- [ ] 事件入审计表(复用 `agnet_audit_events`)
- [ ] 给桌面客户端 push 接口(已有 SSE 通道复用)
### Phase 2(**1 周联调**)
- 两侧用 mock-emit 联调各 event_type
- 故意制造签名错 / 体格式错 / 网络断 / 慢响应等 edge case,验证重试 + dead letter
- 真实部署端到端验证:phase 变化 / SK 工具调用 / 预算告警
### Phase 3(**生产上线 + 观察 2 周**)
- 灰度 1 个真实部署
- 监控:投递成功率(> 99%)、重试率(< 5%)、p95 接收延迟(< 300ms)、dead letter 数(每天 < 5)
- 全量上线
---
## 11. 安全与合规
### 11.1 数据最小化
- payload 里**严禁**包含原始 prompt、原始代码、原始密钥
- 所有"内容"字段都是 `*_summary`,由 Agent Manager 主动截断 + 脱敏
- 文件 / 工具输出超过 1KB 时只传摘要 + size + 引用 ID
### 11.2 IP 白名单(可选)
Heicode 可在 callback endpoint 加 IP CIDR 白名单(Agent Manager 出网 IP 段),HMAC 之上再加一层。但 Cloudflare 代理后这个白名单意义有限,**HMAC 是真正的安全边界**。
### 11.3 审计
每个收到的事件都落 `agnet_audit_events` 表(v1.4.2 已经实装),含:
- event_id / event_type / deployment_id
- delivery_attempt(看重试情况)
- signature_verified(true/false)
- processed_at / processing_duration_ms
---
## 12. 版本演进
- 本契约为 `v1.0`
- 未来添加新 `event_type` 是 **minor**(v1.1),Heicode 端忽略未知 event 应返回 200 + warning(不让 Agent 重试)
- 修改现有 event 字段或签名规范是 **major**(v2.0),双方协商升级
- Heicode 收到 `X-Agnet-Signature-Version: v2` 但本机只支持 v1 → 返回 400 `SIGNATURE_VERSION_UNSUPPORTED`
---
## 13. 待 Agent Manager 团队确认的开放问题
1. ❓ `signing_secret_ref` 走 Vault 引用,需要 Agent Manager 这边有 Vault 客户端能解 — 现状如何?是否需要换成 Heicode 直接给明文密钥?
2. ❓ §6 mock-emit 接口你们能在 staging 提供吗?没这个我们这边没法联调
3. ❓ §5.5 高危审批的 `auto_deny_at` TTL 默认多久合适?我们这边建议 1 小时
4. ❓ §5.10 `agent.crashed` 的 `last_log_tail` 截断到多少字节?建议 1KB
5. ❓ §10 phase 1 的 1-1.5 周评估,跟你们实际工作量是否一致?
---
## 14. 附录
### 14.1 Heicode 端等价代码(参考实现)
```go
// heicode/middleware/agnet_callback_signature.go (待实现)
//
// 校验 X-Agnet-Signature 的中间件。复用 V2 device-signature 那套
// canonical-string + HMAC 模式,只是密钥源改成 Vault 引用 + signing
// scheme 改成 HMAC-SHA256 而非 Ed25519。
//
// 失败响应统一走 400 + retryable:false,不让 Agent Manager 在协议
// 错的情况下白重试。
```
### 14.2 Heicode 端落库参考
```sql
-- 已存在的 agnet_audit_events 表
-- (Sprint 1, 2026-05-22 上线)
-- 加一个 event_source 列区分 'control_plane' (Heicode 自己触发的)
-- 和 'callback' (从 Agent Manager 反推的)
ALTER TABLE agnet_audit_events ADD COLUMN event_source VARCHAR(32) DEFAULT 'control_plane';
```
---
**Heicode Manager 团队联系人**:陈晨 (zsbgnw@gmail.com)
**草案版本**:v1.0-draft-1
**期望评审周期**:2026-05-30 前给反馈