Ghostfactory-art/spanchain
GitHub: Ghostfactory-art/spanchain
Span Chain 是一款基于 SHA-256 哈希链的 AI agent 审计追踪系统,为生产环境提供防篡改、离线可验证的加密证据和确定性重放能力。
Stars: 1 | Forks: 0
每个 agent 都会留下记录。 我们负责保存。
面向生产级 AI agent 的防篡改审计追踪。仅追加。
加密可验证。确定性可重放。
Span Chain 将 **agent 会话** 视为分析单元——而不是单个 LLM 调用。
整个运行过程保持其父/子 span 层级结构,并记录到一个
**不可变的、哈希链验证的账本** 中,以此作为事实来源。
重放已记录的会话时,其 span 将 **被重新摄取到一个全新的、独立验证的链中**
——结构完全相同,使用全新的 `run_id`,无需重新执行 LLM。重放
验证的是 Span Chain 的完整性,而非你的 agent 的行为。
静默失败——HTTP 200,错误答案——将变得可检查,而不再是无法重现。
每个 agent 动作都会生成一份 **加密凭证** ——这是一份防篡改记录,
通过 SHA-256 与上一个动作进行链式关联。仅追加。可通过
`verify_ledger` 进行离线验证——无需 LLM 调用或外部服务。
## Span Chain 的对比
| | LangSmith / Langfuse | Span Chain |
|---|---|---|
| **目的** | 开发者调试、可视化 | 生产环境可审计性、完整性 |
| **Traces** | 可变,由供应商控制 | 仅追加,哈希链式 |
| **重放** | 重新运行 LLM ($) | Cassette 重放 ($0) |
| **证据** | 日志 | 加密验证 |
| **托管** | 供应商 SaaS | 自托管,MIT |
| **调试成本** | 每次重试 = LLM 调用 | Cassette 重放 $0 |
| **架构** | 无状态 Python API | Elixir/OTP 每次运行隔离 |
**LangSmith** 专为开发调试和 trace 可视化而构建。
**Span Chain** 专为生产环境的可审计性和防篡改证据而构建。
**Langfuse** 专为追踪和分析而构建。
**Span Chain** 专为加密验证和无需 LLM 调用的确定性重放而构建。
**Elixir/OTP 每次运行隔离** —— 每个 agent 运行都会获得自己独立的受监督进程;
一次运行中的崩溃绝不会影响其他运行。
如果你的目标是遵守 EU AI Act,Span Chain 的防篡改
账本提供了防篡改的审计追踪,使得 Article 12 的可追溯性变得可验证。
**面向合规项目的审计追踪:** 旨在支持 EU AI Act Article 12 的可追溯性、SOC 2 审计追踪控制以及 HIPAA 审计日志记录要求。
Span Chain 提供证据层——而你的合规项目负责提供其余部分。
## 工作原理
账本中的每个条目都包含前一个条目的 SHA-256 哈希。
被篡改的记录和丢失的 epochs 是 **可检测到的**,而不是被忽略。
## 实际效果
Trail —— 一次运行的完整 span 树,每个条目都经过哈希链验证,并内联捕获了 agent 自身的推理过程。
Evals compare —— 结构化的 span 树差异对比,精准定位两次运行产生分歧的确切 span。
## 属性

Verified
Every entry cryptographically linked to the last
|

Deterministic Replay
Same session → identical chain, always
|

Tamper Detection
Dropped epochs and mutations surface automatically
|
Non-repudiation
Cryptographic proof that an agent action occurred and was not modified
|
## 架构
```
SDK (OTLP / JSON)
→ Ingest (normalize, span tree)
→ Hash-Chain Ledger (source of truth · immutable · verifiable)
├── Deterministic Replay
├── Evals & Compare
└── Audit Trail
```
## 快速开始
需要 Docker Compose v2 和一个 `.env` 文件:
```
git clone https://github.com/ghostfactory-art/spanchain.git
cd spanchain
cp .env.example .env
# 编辑 .env — 设置 POSTGRES_PASSWORD, GF_API_KEY 和 SECRET_KEY_BASE
docker compose up
```
UI 位于 **http://localhost** · 摄取 API 位于 **http://localhost/ingest**
**发送 trace (OTLP/HTTP JSON):**
```
curl -X POST https://localhost/v1/traces --insecure \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SPANCHAIN_KEY" \
-d @your-trace.json
```
或者使用位于 `http://localhost/ingest` 的纯 JSON 端点——无需 OTLP SDK。
原生支持 **LangChain, CrewAI, LlamaIndex, AutoGen 和 Pydantic AI**
,通过标准的 OpenTelemetry (OTLP)——无需特定框架的 SDK。
## OTLP 兼容性
Span Chain 摄取 **OTLP/HTTP JSON** (`POST /v1/traces`) —— 标准的子集。
完全的 OTel 直接替换兼容性并不是 L2 的目标;缺失的字段会被静默忽略
(根据 ADR-004 定义为 `lossy-but-visible`)。
### Attribute 值类型
| OTLP 类型 | Span Chain 行为 |
|---------------|---------------------------------|
| `stringValue` | 存储为 string ✅ |
| `intValue` | 存储为 integer ✅ |
| `boolValue` | 存储为 boolean ✅ |
| `doubleValue` | 存储为 float ✅ |
| `arrayValue` | JSON 序列化的 string ⚠️ |
| `kvlistValue` | JSON 序列化的 string ⚠️ |
### 必需的 resource attribute
`service.instance.id` **必须** 存在——它将映射到 `run_id`。
如果缺失 → HTTP 400 `missing_run_id`。
```
{
"resourceSpans": [{
"resource": {
"attributes": [{
"key": "service.instance.id",
"value": { "stringValue": "my-agent-run-001" }
}]
},
...
}]
}
```
### 被忽略的内容
- `events`, `links` —— 不存储
- scope attributes —— 不存储(仅保留 resource + span attributes)
- `traceState`, `droppedAttributesCount` —— 不存储
### HTTP 响应
成功的摄取 → HTTP **200** + `{"partialSuccess":{"rejectedSpans":0}}`。
(不是 202——只有 `/ingest` 端点才会返回 202。)
### OTel Collector bridge
你是否有标准的 OTel SDK 但无法设置 `service.instance.id`?
请使用 OTel Collector 作为中间件:
```
# OTel Collector bridge → Span Chain
# 映射 service.name → service.instance.id(run_id carrier 用于 Span Chain)
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318"
processors:
transform/spanchain:
trace_statements:
- context: resource
statements:
- set(attributes["service.instance.id"], attributes["service.name"])
exporters:
otlphttp/spanchain:
endpoint: "https://your-spanchain-instance/v1/traces"
headers:
Authorization: "Bearer ${env:GF_API_KEY}"
service:
pipelines:
traces:
receivers: [otlp]
processors: [transform/spanchain]
exporters: [otlphttp/spanchain]
```
## SDKs
两个 SDK 均在此 repo 中发布,并使用 OTLP/HTTP JSON(子集——请参阅 [OTLP 兼容性](#otlp-compatibility))。
**Python:**
```
pip install ./sdk/python
```
**TypeScript:**
```
npm install ./sdk/typescript
```
使用示例位于 [`sdk/python/README.md`](sdk/python/README.md) 和
[`sdk/typescript/README.md`](sdk/typescript/README.md) 中。
## 状态
v0.x · 2026 年 6 月发布 · 正在积极开发中。
一款 **[GhostFactory](https://ghostfactory.art)** 产品 —— [spanchain.art](https://spanchain.art)
## 公开内容
默认情况下,`/trail` 和 `/eval/:id` 无需身份验证即可访问。
这些视图会暴露元数据:运行 ID、span 名称、时间以及 agent 配置差异
(`gf.agent.*` 属性)。**Span payload 仍受 token 门控限制** (`GF_API_KEY`)。
对于面向互联网或共享的实例,请在 `.env` 中设置 `TRAIL_AUTH_ENABLED=true`。
这将在 Trail/Eval 视图上启用 HTTP Basic Auth(密码 = `GF_API_KEY`)。
## 已知问题
**TLS 证书 (localhost):** 使用默认的 `DOMAIN=localhost` 时,Caddy 会使用其自带的本地 CA 终止 HTTPS,因此在首次运行时,你的浏览器会显示 SSL 警告,并且 `curl` 会因
证书错误而失败。只需信任本地 CA 一次:
```
docker compose exec caddy caddy trust
```
之后重启浏览器(在 Windows/Docker Desktop 上通常需要这样做;在 WSL2 上,你可以
确认证书已进入 `/etc/ssl/certs/`)。若要跳过信任,请改为按请求绕过——
使用 `curl --insecure` 或点击浏览器的“高级”警告。当 `DOMAIN` 是一个
真实域名时不需要这样做(Caddy 会使用 Let's Encrypt)。
**Windows (WSL2):** `entrypoint.sh` 中的行尾符问题——如果容器以
`exec format error` 退出,请在构建之前运行 `dos2unix entrypoint.sh`。
**macOS (Apple Silicon):** 未经测试。应该可以通过 Docker Desktop ARM 模拟运行。
**Linux:** 未经测试。预计标准的 `docker compose up` 即可运行。
## 许可证
MIT —— 请参阅 [LICENSE](LICENSE)。
标签:Elixir, 人工智能, 合规追踪, 审计日志, 密码学, 手动系统调用, 数据溯源, 测试用例, 用户代理, 用户模式Hook绕过, 请求拦截, 逆向工具