证据链
wesgine 内置接地声明(Grounded Claims)架构,通过 per-Run hash chain 和结构化证据记录,为 AI Agent 的每一步行为提供可验证的审计追踪。
概览
Run 执行
│
├── 每次工具调用 → EvidenceRef 记录
├── 每个模型响应 → EvidenceRef 记录
└── 每个决策点 → EvidenceRef 记录
│
▼
per-Run Hash Chain
│
├── 链式哈希(前一条的 hash → 下一条的 prev_hash)
└── 不可篡改(插入/删除/修改会破坏链)
│
▼
持久化到 state.db
│
├── GET /observe/evidence → JSONL 流式导出
└── GET /audit/export → 完整审计导出
接地声明架构
设计原则
"接地声明"意味着 AI Agent 的每个行为和决策都有据可查:
- 每一步可追溯:从最终结果反向追踪到原始输入
- 机械可验证:hash chain 可由程序自动校验,不依赖人工
- 防篡改:任何中间环节的修改都会破坏后续哈希链
- 完整导出:可完整导出为 JSONL 用于外部审计
三层分离
| 层 | 职责 | 实现 |
|---|---|---|
| 收集层 | 记录原始事件 | EventEmitter 在 Loop 的每个关键点发出事件 |
| 存储层 | 持久化与链式哈希 | state.db 的 wes_evidence 表 |
| 呈现层 | 导出与查询 | HTTP API + JSONL 流 |
EvidenceRef 结构
每条证据记录包含:
{
"id": "ev-a1b2c3d4",
"run_id": "run-x1y2z3",
"seq": 42,
"timestamp": "2026-09-14T13:00:00.123Z",
"type": "tool_call",
"data": {
"tool": "exec",
"input": {"command": "go build ./..."},
"output": {"exit_code": 0, "stdout": "..."},
"duration_ms": 1200
},
"hash": "sha256:a1b2c3...",
"prev_hash": "sha256:x1y2z3..."
}
字段说明
| 字段 | 说明 |
|---|---|
id | 证据条目唯一标识 |
run_id | 所属 Run 标识 |
seq | Run 内序号(从 0 递增) |
timestamp | 精确到毫秒的时间戳 |
type | 事件类型(见下表) |
data | 结构化事件数据 |
hash | 本条的 SHA-256 哈希 |
prev_hash | 前一条的哈希(链式) |
事件类型
| type | 说明 | data 内容 |
|---|---|---|
run_start | Run 开始 | actor, session_id, agent_id, model |
llm_request | LLM 请求 | model, message_count, token_estimate |
llm_response | LLM 响应 | model, tokens_used, has_tool_calls |
tool_call | 工具调用 | tool, input, output, duration_ms |
tool_error | 工具错误 | tool, input, error |
governance | 治理决策 | zone, decision, rule |
memory_write | 记忆写入 | kind, layer, content_hash |
hitl_request | HITL 请求 | type, prompt |
hitl_response | HITL 响应 | decision, actor |
settlement | 认知结算 | degraded, session_state_hash |
run_end | Run 结束 | reason, turns, total_tokens |
per-Run Hash Chain
链式结构
Evidence[0] → Evidence[1] → Evidence[2] → ...
│ │ │
hash=H(data) hash=H(data) hash=H(data)
prev_hash=∅ prev_hash=H0 prev_hash=H1
哈希计算
H(evidence) = SHA-256(
run_id || seq || timestamp || type || JSON(data) || prev_hash
)
验证算法
def verify_chain(evidences):
"""验证 per-Run 证据链完整性"""
for i, ev in enumerate(evidences):
# 1. 序号连续
assert ev.seq == i
# 2. 前向链接
if i == 0:
assert ev.prev_hash == ""
else:
assert ev.prev_hash == evidences[i-1].hash
# 3. 哈希正确
expected = sha256(
ev.run_id + str(ev.seq) + ev.timestamp +
ev.type + json(ev.data) + ev.prev_hash
)
assert ev.hash == expected
return True # 链完整
切片不可验证
证据链是逐 Run hash chain,切片后缺环无法校验。这是 /observe/evidence 抬到 cell:admin 且不做 per-actor 过滤的原因(INV-OBS-09)——"只给我看我自己的审计记录"不是审计。
JSONL 导出
API
GET /cells/{id}/observe/evidence
→ Content-Type: application/x-ndjson
→ 流式返回每行一个 JSON 对象
格式
每行一个 JSON 对象,按 run_id + seq 排序:
{"id":"ev-001","run_id":"run-abc","seq":0,"type":"run_start","data":{...},"hash":"sha256:...","prev_hash":""}
{"id":"ev-002","run_id":"run-abc","seq":1,"type":"llm_request","data":{...},"hash":"sha256:...","prev_hash":"sha256:..."}
{"id":"ev-003","run_id":"run-abc","seq":2,"type":"tool_call","data":{...},"hash":"sha256:...","prev_hash":"sha256:..."}
审计导出
完整的审计数据导出支持多种格式:
GET /cells/{id}/audit/export?format=jsonl&from=2026-09-01&to=2026-09-14
GET /cells/{id}/audit/export?format=csv&from=2026-09-01&to=2026-09-14
审计摘要:
GET /cells/{id}/audit/summary
→ {
"total_runs": 1250,
"total_evidence": 48000,
"chain_integrity": "verified",
"period": {"from": "...", "to": "..."}
}
审计用途
合规审计
金融/法律/医疗等受监管行业需要完整的 AI 决策审计追踪:
审计员请求:
"请提供 2026年9月 法务部门 AI 助手的所有决策记录"
→ GET /cells/dept-legal/audit/export?format=csv&from=2026-09-01&to=2026-09-30
→ 包含每次对话、工具调用、治理决策的完整链
→ hash chain 验证确认无篡改
事故回溯
当 AI 产生不当行为时,通过证据链精确回溯:
// 查看特定 Run 的所有工具调用
tools, _ := cell.Observe().RunTools(ctx, runID)
for _, t := range tools {
fmt.Printf("[%s] %s(%v) → %v\n",
t.Timestamp, t.Tool, t.Input, t.Output)
}
行为归因
结合 actor 标签,可以按人归因行为:
// 查看 alice 的所有 Run
runs, _ := cell.Observe().ListRuns(ctx, wesgine.ObserveFilter{
Actor: "alice",
From: startDate,
To: endDate,
})
与 Observe 体系的关系
证据链是 Observe(可观测性)体系的子集:
| 观测面 | 数据 | 用途 |
|---|---|---|
| Token Usage | token 计数 | 成本追踪 |
| Run Traces | Run 摘要 | 性能分析 |
| Tool Calls | 工具调用明细 | 行为分析 |
| Evidence Chain | 完整链式证据 | 合规审计 |
| Crash Log | 崩溃记录 | 故障诊断 |
Actor 边界(INV-OBS-08/09/10)
| 端点 | Actor 过滤 | 说明 |
|---|---|---|
/observe/runs | ✅ 按 actor 过滤 | 普通用户只看自己的 Run |
/observe/token-usage | ✅ 按 actor 过滤 | 普通用户只看自己的用量 |
/observe/evidence | ❌ 不过滤,抬 admin | hash chain 不可切片 |
/audit/* | ❌ 不过滤,抬 admin | "只给我看我的审计"不是审计 |
最佳实践
- 定期验证链完整性:使用审计摘要 API 确认
chain_integrity: verified - 保留导出备份:定期 JSONL 导出存储到外部审计系统
- 金融合规启用 Regulated 预设:
Compliance: "financial"自动启用严格审计 - 不要尝试切片证据链:查询单 actor 的行为使用 Run 列表而非证据链
- 活用 Run Tools 接口:事故回溯时先
ListRuns定位,再RunTools看细节
相关 API
| 端点 | 说明 |
|---|---|
GET /cells/{id}/observe/evidence | 证据链 JSONL 流 |
GET /cells/{id}/audit/export | 审计导出(jsonl/csv) |
GET /cells/{id}/audit/summary | 审计摘要 |
GET /cells/{id}/observe/runs | Run 列表 |
GET /cells/{id}/observe/runs/{runID} | Run 详情 |
GET /cells/{id}/observe/runs/{runID}/tools | Run 工具调用 |