mcpField
A
agentic-ledger

agentic-ledger

本地服务
github.com/ShekharBhardwaj数据与分析74 天前更新

关于 agentic-ledger

Agentic Ledger 是面向 AI Agent 运行的本地优先观测代理,适合需要检查活动和成本的开发者与团队。它记录请求和响应,并通过实时仪表板与 API 展示会话、循环活动、成本及重放。

主要功能

  1. 01通过代理捕获请求和响应
  2. 02跟踪会话、成本和循环运行
  3. 03检查调用轨迹、流程和详情
  4. 04将记录的运行重放到其他模型
  5. 05设置运行成本上限并阻止后续调用

适用场景

  1. 01调查 Agent 运行中的调用和提示词
  2. 02比较使用不同模型的记录运行
  3. 03为 Agent 循环设置支出上限

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"shekharbhardwaj-agentic-ledger": {
"command": "uvx",
"args": [
"agentic-ledger"
]
}
}
}
启动命令uvx agentic-ledger

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiagentic-ledger0.15.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

README 配图

Agentic Ledger

CI CodeQL PyPI Python versions Docker License: MIT MCP server on Glama BYOAIK status

AI Agent 运行时可观测性——准确查看 Agent 做了什么、为何这么做,以及花费了多少。

网站: agentic-ledger.dev

这些数字应当与您的服务提供商账单一致。如果不一致,这就是我们希望您报告的错误。

适用于任何 Agent 框架、任何大模型服务提供商、任何模型网关。无需更改代码。将 Agent 指向代理,即可自动捕获所有信息。


工作原理

Agentic Ledger 作为透明代理,运行在您的 Agent 与大模型服务提供商之间。它会拦截每个请求和响应,为其分配一个 action_id,保存后再原样返回上游响应。您的 Agent 不会察觉代理的存在。完整介绍,包括示意图和供贡献者参考的模块图,请参阅 ARCHITECTURE.md。

Your Agent  →  Agentic Ledger Proxy  →  OpenAI / Anthropic / LiteLLM / any LLM
                      ↓
               SQLite or Postgres
                      ↓
               Live Dashboard + API

快速入门

步骤 1 - 启动代理

从 Helicone 或 LangSmith 迁移而来?迁移页面只需两行即可完成配置转换。正在使用 Headroom 这类上下文压缩器?它们可以串联。

只需两条命令,无需配置,也不会让终端一直被占用:

uv tool install agentic-ledger    # or: pipx install agentic-ledger, or pip install -U agentic-ledger
agenticledger start     # runs in the background; terminal freed

使用工具管理的安装方式(uv tool / pipx)会获得独立的隔离环境,并在 PATH 上提供一个明确无歧义的命令入口,因此被其他 Python 环境中的副本覆盖的情况会很少,也能通过 doctor 检测;agenticledger upgrade 始终只代表一种操作。普通 pip 也可以使用;如果机器上出现多个相互冲突的安装,agenticledger doctor --fix 会帮您理清。

agenticledger start 会显示仪表板 URL,并将终端还给您——关闭窗口不会停止服务。agenticledger status 会告知服务是否正在运行且状态正常,agenticledger logs 会显示服务正在做什么,agenticledger stop 会关闭服务。无论如何都想要配置文件?agenticledger init 会生成一个带注释的配置文件;其中各项配置请参阅配置。

或者使用 Docker(无需安装 Python):

docker run -p 8000:8000 \
  -e AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com \  # optional: omit to route by call format
  -v $(pwd)/data:/data \
  ghcr.io/shekharbhardwaj/agentic-ledger:latest

镜像支持多架构(amd64/arm64),以非 root 用户身份运行,并且每个版本都使用 Sigstore 签名并附带 SBOM。需要加固共享部署(TLS、身份验证密钥、脱敏、验证)?请参阅 部署指南。 使用 Anthropic / Claude? 无需配置:未设置上游时,代理会根据调用的线路格式进行路由,因此 Anthropic 风格的调用会发送到 Anthropic,OpenAI 风格的调用会发送到 OpenAI,通过同一个代理并行处理。设置显式的 upstream_url(例如 LiteLLM 或 OpenRouter 之类的网关、LM Studio,或指定的提供商)后,会切换为经典的一个代理对应一个提供商的行为,并包含不匹配提示。

或者使用 docker compose(默认使用 SQLite,参见 docker-compose.yml):

AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com docker compose up

使用 Postgres 时,叠加此配置覆盖文件;它会替换 DSN 并添加数据库服务,镜像已包含驱动:

docker compose -f docker-compose.yml -f docker-compose.postgres.yml up

使用 uv:

uv add agentic-ledger
AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com uv run python -m agenticledger.proxy

使用 pip:

python -m venv venv && source venv/bin/activate
pip install -U agentic-ledger
AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com ./venv/bin/python -m agenticledger.proxy

使用 Postgres? 安装额外依赖并设置 AGENTICLEDGER_DSN:

pip install "agentic-ledger[postgres]"
AGENTICLEDGER_DSN=postgresql://user:password@localhost/agenticledger

注意:Docker 镜像仅使用 SQLite。使用 Docker 配置 Postgres 时,请改用 pip 安装。

使用 OpenTelemetry? 安装额外依赖并设置 AGENTICLEDGER_OTEL_ENDPOINT:

pip install "agentic-ledger[otel]"
AGENTICLEDGER_OTEL_ENDPOINT=http://localhost:4318

代理会在 http://localhost:8000 启动。使用 agenticledger start 启动时,追踪记录会保存到 ~/.agenticledger/agenticledger.db(后台服务统一使用此目录,与启动位置无关);在前台运行时(agenticledger serve / python -m agenticledger.proxy),会保存到当前文件夹中的 agenticledger.db;在 Docker 中则保存到 /data/agenticledger.db。


第 2 步 - 将 Agent 指向代理

对于 Claude Code、BMAD 或 OpenClaw,只需运行一条命令即可写入配置(会备份、合并并适配 Docker):

agenticledger connect claude-code    # or: bmad, openclaw

对于其他情况,只需两项更改:将 base_url 设为代理地址,并添加会话 ID 标头,将调用归入同一次运行。其他内容——API 密钥、模型、消息——都保持不变。

OpenAI:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",  # ← proxy
    api_key="your-openai-key",
    default_headers={"x-agenticledger-session-id": "run-1"},
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Research the top 3 AI trends in 2026"}],
)

Anthropic(无需配置上游:/v1/messages 调用会自动路由到 Anthropic):

import anthropic

client = anthropic.Anthropic(
    base_url="http://localhost:8000",  # ← proxy
    api_key="your-anthropic-key",
    default_headers={"x-agenticledger-session-id": "run-1"},
)

Azure OpenAI: 将 AzureOpenAI(azure_endpoint="http://localhost:8000") 指向账本,并将你的资源设为上游;部署的价格会根据响应中指定的模型计算。参见 Azure 指南。

AWS Bedrock: 安装 agentic-ledger[bedrock],通过标准凭证链为账本提供 AWS 凭证,并将 boto3(endpoint_url)或 Claude Code(ANTHROPIC_BEDROCK_BASE_URL)指向它;账本会自行为每次调用重新签名。两种线路格式均受支持:InvokeModel 以及现代的 Converse/ConverseStream API。参见 Bedrock 指南。

LiteLLM / OpenRouter / 任意网关:

# Point Agentic Ledger at your gateway
AGENTICLEDGER_UPSTREAM_URL=http://localhost:4000 uv run python -m agenticledger.proxy

# Then point your agent at Agentic Ledger
client = OpenAI(base_url="http://localhost:8000/v1", ...)

第 3 步 - 打开仪表板

http://localhost:8000

随着调用进入,Web 应用会通过 WebSocket 实时更新。无需刷新。

  • 与网站匹配的设计 - 控制面板采用与 agentic-ledger.dev 一致的炭灰色表面、冰蓝色点缀、几何浣熊标志和字体。Session Overview 新增已记录费用、调用次数、Token 总量和单次调用费用图表。Loop Lens 将迭代费用与“你离开期间”时间线并列展示。未知的调用价格会明确标出;所有图表均使用已捕获的账本数据。Calls、Flow、Trace、回放、预算控制以及浅色/深色外观均保留。
  • Loop Lens - 查看每次循环运行及其观测到的状态(运行中/已标记/已声明完成/已结束/调用已阻止),一个展开的指标栏(已记录开支、附带真实记账进度的运行上限、模型调用次数),Overview/Activity/Cache 视图,以及可直接跳转到证据的已记录事件时间线。Block calls 操作可在运行循环触及上限时拒绝其后续调用(可通过 Allow calls again 解除;被阻止的 Agent 无法自行解除)。还可查看逐次迭代明细,以及所有标记的通俗说明。点击 ⇆ 选择任意两次运行并排对比:先播放结构回放(逐次播放已记录的调用、逐步填充上下文堆栈以呈现模型读取的内容、展示发往工具的操作、结果重新加入对话或因下一次调用开始新对话而被丢弃,并以同一比例呈现两次运行的相同起点),然后对比费用、迭代次数、调用次数、缓存读取、标记和时长,并显示带正负号的差值;此外还有提示词漂移对比,精确展示两次运行的系统提示词和开场指令发生了哪些变化。examples/loop-anatomy/ 记录了在同一任务上运行 Ralph 循环和 ReAct 循环的情况,可用于展示这两种模式。
  • Sessions - 简洁易读的平铺行,以及三种视图:调用行(时间、模型、单一状态、延迟、费用),展开后可查看包含四个标签页(Response、Tools、Prompt、Raw)的检查器;展示 Agent 交接的 Flow DAG;以及包含循环引擎真实父级链接的 Trace 瀑布图。每行都会一眼标明归属:团队徽标、表示真实故障的红色、表示主动拒绝的琥珀色、表示回放的紫色,以及可将每个会话关联到其循环的运行标记。
  • 回放整个运行 - 决定是否切换模型的关键问题不是“它处理单次调用的表现如何?”,而是“我的循环能否撑下来?”选择一次运行或一个会话,再选择目标模型(本地模型免费),每一步都会使用原始输入重新运行。你得到的是成绩单,而不是作业:“40 个关键时刻中有 34 个匹配”,并列出失误之处(“丢弃了工具”),以及两种模型各自的费用。每一步都是真实捕获时刻的如实回放——第一步之后,另一个模型可能会引导对话走向不同方向,因此账本对比的是实际时刻,而不是虚构情节。
  • 随身访问 - agenticledger share 会打开一个由你掌控的 https 隧道(通过 cloudflared,无需账户)、打印配对链接,并在终端显示二维码:用手机摄像头扫描,就能在掌中查看控制面板,包括紧急停止开关、停止所有调用和费用上限。使用 --wifi 获取同一网络内的链接,使用 --rotate 解除所有设备的配对,或在控制面板的 ⚿ 面板中点击 Pair a device。本地机器无需密钥;其他设备则需要输入自动生成的配对密钥。控制面板适配手机:一次显示一个面板,提供返回按钮和前进/后退箭头以切换运行。
  • 全队列级别的强制停止 - Stop all calls 是可一次停止所有 Agent 的紧急停止功能:在 Loop Lens 中点击一个按钮(需确认);启用期间每个页面都会显示横幅;即使重启也会持续生效,直到有人解除。模型和提供商的允许/拒绝列表(AGENTICLEDGER_ALLOW_MODELS、AGENTICLEDGER_DENY_PROVIDERS 等,支持 glob 模式)会按规则名称拒绝不合适的模型;团队卡片也可以设置自己的列表,但只能进一步收紧整个队列的限制。每次拒绝都会留下记录:速率限制、循环防护、预算、费用上限、紧急停止开关和停止所有调用,都会以琥珀色 blocked: 行记录拒绝原因,并计入 Reports 和 /metrics。解除循环阻止可直接在控制面板的会话中操作,无需重启。账本只会拒绝或记录;绝不会改写、重定向或替换调用。
  • 缓存审计 - 每次运行都会回答“我是否为重复文本支付了全价?”实际获得的折扣精确取自提供商自己的缓存报告;未节省的金额会标明为估算,并展示估算方法;每项判定都会说明原因并提供一行改进建议,包括“没有遗漏,可以放心”。也可通过 GET /api/runs/{id}/cache-audit 查看。
  • 由你保留 - 可选择深色、浅色或跟随系统外观(选择保存在浏览器本地),并使用保留调查上下文的 URL:可深度链接到运行、会话和单次调用(#/sessions/<id>/calls/<action_id> 会打开会话并展开该调用),支持正常的后退/前进操作,普通链接绝不包含凭据。列表默认加载最新的 50 条,按一次即可继续加载更早记录;筛选器适用于全部历史记录;侧边栏中的计数显示真实总数。
  • 命名实例 - agenticledger start --name demo --port 8003 可在日常使用的账本旁启动另一个账本:各自拥有独立状态和数据库,其控制面板会显示琥珀色名称标记,不会与真正的实例混淆。stop、status、logs、share 和 run 均支持 --name。
  • 费用计量器 - 运行详情会实时显示费用:目前已花费金额、每小时消耗金额,以及“按当前速度,到上午 8:00 将花费 $Y”。可为任意运行设置费用上限;达到上限时,代理会立即拒绝后续调用(显示琥珀色状态,不产生费用),直到你提高或清除上限。上限在重启后仍然有效,也会保护自动检测到的循环。达到 80% 时会触发 webhook 警报。
  • 名称、置顶、项目、图标 - 将 cc-73a26366 改名为“隔夜身份验证修复”,用 ★ 将重要项置顶,按项目归档工作;Sessions 视图会按区块展示:每个项目一个标题,其会话列在下方,未归档项则显示在最后。归档到项目下的运行,其会话也会一并归档。通过 ✎ 编辑器的选择器为循环或会话设置图标和颜色,让它们一眼就能区分。
  • 设置 - 点击 ⚙ 可查看代理实际运行时使用的配置:生效的配置文件、上游服务、预算、回放目标;每行都会标明来源是 file/env/default,且隐藏机密信息。配置文件可以设置的每一行都有 Change 链接:选择或输入新值后,系统会将其写入配置文件,再点击 Restart now,即可在控制面板中应用所有更改(账本会在原处重新执行自身)。如果某行由环境变量设置,也会明确标出,因为环境变量始终优先。
  • 回放与假设分析 - 打开任意调用并点击 ↻ Replay:选择目标(面板会列出本地服务实际加载的模型),捕获的原始提示词会在该目标上精确重放——可选相同提供商、另一家提供商,或通过 LM Studio 使用免费的本地模型;工具调用、架构和系统提示词会自动在 Anthropic 与 OpenAI 的线缆格式之间转换。即使调用被你自己的预算阻止,也可以回放——上限可以拒绝调用,但你仍能查看原本会发生什么,费用为 $0。回放会通过 ↩ Open original 链接到其原始调用。假设分析框会先回答更简单的问题:使用纯数学重新计算任意运行或会话在另一模型上的费用,不发起 API 调用。(配置 AGENTICLEDGER_REPLAY_API_KEY 和/或各提供商的 AGENTICLEDGER_REPLAY_*_KEY 目标。)
  • Reports - 了解资金流向:每日费用、带有延迟 p50/p95/p99的模型构成、各 Agent 的总费用、按团队汇总的表格(显示每个团队的费用与其卡片每日额度的对比,可一眼看出“谁的额度用完了?”),以及缓存节省金额——提示词缓存流量若按完整输入费率计费会花费多少,以及实际花费多少。错误和阻止事件在所有视图中都会分别计数:红色 = 出现故障,琥珀色 = 账本主动拒绝——健康的防护机制不会让健康的 Agent 显得有问题。
  • 搜索 - 在所有会话中按提示词、输出、Agent 名称或用户 ID 进行全文搜索

配置

agenticledger init 会写入 agenticledger.toml,其中每个选项都处于注释状态。 取消注释你需要的选项——可用的配置如下所示:

[proxy]
port = 8000
upstream_url = "https://api.anthropic.com"
db = "sqlite:///agenticledger.db"

[keys]
# Prefer *_file: the file's contents are the key, so no secret lives in
# this file or your shell history (chmod 600 the key file).
api_key_file = "~/.agenticledger/api.key"       # dashboard/admin access
ingest_key_file = "~/.agenticledger/ingest.key" # closes the open relay

[budgets]
daily = 25.0          # whole-ledger daily ceiling, USD
session = 5.0         # per-session ceiling

[replay]
# Free local replay via LM Studio (any key works there):
openai_url = "http://localhost:1234"
openai_key = "lm-studio"

三条规则:

  1. 配置文件按以下顺序查找: AGENTICLEDGER_CONFIG,然后是 ./agenticledger.toml(你启动命令时所在的文件夹),最后是 ~/.agenticledger/config.toml。使用第一个匹配项;启动横幅会显示 当前生效的文件。
  2. 命令中输入的任何内容都会覆盖文件中的设置。 环境变量会逐项覆盖设置(AGENTICLEDGER_PORT=9000 agenticledger start 会在本次运行中使用 9000, 不会修改文件)——这也是为什么通过环境变量配置的 Docker 和 CI 设置不受影响。
  3. 更改需重启后生效(先运行 agenticledger stop,再运行 start)。

以下环境变量参考中的每项设置都有对应的配置文件选项; [env] 部分会原样传递其他任何 AGENTICLEDGER_* 变量。


按步骤配置各提供商

以下所有提供商都使用同一个代理;唯一的变化是指向该代理的基本 URL。 每个配置示例都假设代理已启动(agenticledger start),并以同样的检查结束:发起一次调用,打开 http://localhost:8000,然后在 Sessions 中查看。

OpenAI(以及任何兼容 OpenAI 的 API)

  1. 将客户端指向代理:
    export OPENAI_BASE_URL=http://localhost:8000/v1
    
  2. 保持 OPENAI_API_KEY 原样不变——代理会原样传递你的 身份验证标头。
  3. 发起一次调用;它会带有 O 标记,显示在 Sessions 中。

Anthropic

  1. 将客户端指向代理:
    export ANTHROPIC_BASE_URL=http://localhost:8000
    
  2. 保持 ANTHROPIC_API_KEY 原样不变。
  3. 发起一次调用;它会带有 A 标记显示。不需要上游配置—— 代理会根据线路格式,将 Anthropic 格式的调用路由到 Anthropic。

AWS Bedrock(直接捕获)

  1. 通过标准凭证链为 ledger 提供独立的 AWS 凭证 (环境变量、~/.aws 配置文件或实例角色),并限定为 bedrock:InvokeModel 和 bedrock:InvokeModelWithResponseStream, 然后安装额外依赖并重启:
    pip install "agentic-ledger[bedrock]"
    agenticledger stop && agenticledger start
    
  2. 检查 ⚙ Settings 面板:Bedrock 行应显示“正在以 ledger 的身份在 中签名”。
  3. 将客户端指向代理——Claude Code:
    export CLAUDE_CODE_USE_BEDROCK=1
    export ANTHROPIC_BEDROCK_BASE_URL=http://localhost:8000
    
    boto3:boto3.client("bedrock-runtime", endpoint_url="http://localhost:8000")。
  4. 发起一次调用;它会带有橙色 B 标记显示。ledger 会移除调用方的 身份,并使用自身凭证重新签名。完整指南: docs/integrations/bedrock.md。

通过公司网关使用 AWS Bedrock

许多公司会通过网关接入 Bedrock,并由网关自行处理身份验证;此时 Claude Code 的配置会包含 CLAUDE_CODE_SKIP_BEDROCK_AUTH=1,并将 ANTHROPIC_BEDROCK_BASE_URL 指向网关,通常这些设置来自受管理的设置文件。ledger 位于该网关前面,会按 Agent 发送的内容原样转发每次调用,包括标头:无需签名,你这边也无需提供 AWS 凭证。

  1. 告诉 ledger 网关的位置(即之前 ANTHROPIC_BEDROCK_BASE_URL 指向的主机):
    agenticledger config set proxy.bedrock_gateway_url https://bedrock-gateway.company.example
    agenticledger stop && agenticledger start
    
  2. 改为将 Claude Code 指向 ledger:ANTHROPIC_BEDROCK_BASE_URL=http://localhost:8000。如果该值位于 IT 管理的设置文件(/Library/Application Support/ClaudeCode/managed-settings.json)中,它会覆盖所有其他设置,因此必须由 IT 修改;如果它位于 ~/.claude/settings.json 中,则在该文件中编辑。
  3. /health 和 ⚙ Settings 面板会显示“正在按发送给 ... 网关的内容转发”。调用会带有 Bedrock 标记和带区域前缀的模型 ID 显示。

Azure OpenAI

  1. 将上游设为你的资源:
    agenticledger config set proxy.upstream_url https://<resource>.openai.azure.com
    agenticledger stop && agenticledger start
    
  2. 将客户端的 Azure 端点指向 http://localhost:8000;保留原有的 api-key 请求头。
  3. 调用会标记为 azure-openai,并根据响应中注明的模型计价,因此部署别名无法掩盖实际模型。完整指南: docs/integrations/azure-openai.md。

本地模型(LM Studio、搭配 OpenAI API 使用的 Ollama)

  1. 将上游设为本地服务:
    agenticledger config set proxy.upstream_url http://localhost:1234
    agenticledger stop && agenticledger start
    
  2. 在 Agent 中执行 export OPENAI_BASE_URL=http://localhost:8000/v1。
  3. 调用会显示紫色标记,费用为 $0。完整指南: docs/integrations/lm-studio.md。

网关(OpenRouter、LiteLLM)

  1. 将上游设为网关:
    agenticledger config set proxy.upstream_url https://openrouter.ai/api
    agenticledger stop && agenticledger start
    
  2. 执行 export OPENAI_BASE_URL=http://localhost:8000/v1;保留原有的网关 密钥。
  3. 通过子字符串匹配,带网关前缀的模型 ID(“anthropic/claude-...”)可以 正确计价。指南:openrouter.md、 litellm.md。

针对特定框架的配置示例(CrewAI、LangGraph、AutoGen、Vercel AI SDK、 pydantic-ai 等)见 docs/integrations/。


编码 Agent - Claude Code、Ralph 循环及其他

Claude Code(以及大多数编码 Agent)只需设置一个环境变量即可指向代理——无需添加请求头,也无需修改代码:

agenticledger start
export ANTHROPIC_BASE_URL=http://localhost:8000
claude

无需配置上游:调用会路由到与其传输格式匹配的提供商。

Agentic Ledger 会自动识别 Claude Code 流量:每次调用都会标记为 framework=claude-code。此外,每个 Claude Code 会话都会以其真实会话 UUID 显示(也就是 claude --resume 显示的 ID),而不是被归入一个无法区分的汇总类别;提示词缓存的读取和写入也会被准确记录和计费——缓存流量是编码 Agent 实际支出的主要部分。

想用自选名称记录一个循环?在你现有命令前加上一个词即可:

agenticledger run nightly-digest -- python agent.py

你的命令会照常运行;其大模型调用会记入名为 nightly-digest 的运行卡片,每次启动都会计为下一次迭代,因此明天的运行也会加入同一张卡片。无需修改 Agent 代码。启动时添加 --project acme,即可将运行记入仪表板项目。

要运行整夜循环(Ralph 风格的 while :; do cat PROMPT.md | claude -p; done)? 使用带循环标志的同一命令,就会在每次迭代时重新执行你的命令,将每次调用归入该次运行(通过基础 URL,无需请求头),并在满足完成承诺、达到预算上限或达到迭代上限时停止:

AGENTICLEDGER_UPSTREAM_URL=https://api.anthropic.com \
AGENTICLEDGER_COMPLETION_PROMISE="ALL TASKS COMPLETE" \
uv run python -m agenticledger.proxy
agenticledger run overnight --max-iterations 50 --budget 25 -- \
  claude -p "$(cat PROMPT.md)" --dangerously-skip-permissions

/api/runs 中会将每次迭代显示为该次运行的第 N 次迭代;当 Agent 在响应中输出完成承诺时,运行状态会变为 complete,循环也会退出,并显示费用/令牌摘要。run 后面的词是运行名称;如果未指定,则会根据文件夹名和分钟数命名(myproject-0819-1936)。使用相同名称重新运行时,会接续迭代计数,而不是从 1 重新开始。任何现有循环脚本也都适用——你可以自行轮询 GET /api/runs/{run_id},也可以让代理的预算(AGENTICLEDGER_BUDGET_DAILY=25.00)在循环失控时强制停止。

要迭代优化提示词?重新运行,然后在 Loop Lens 中使用 ⇆ compare 对比两次运行——并排比较费用、迭代次数、调用和标志——这样“新提示词是否真的有帮助”就能用数字衡量,而不只是凭感觉判断。

同样的方法也适用于任何支持覆盖基础 URL 的客户端(Codex CLI、 opencode、OpenClaw、基于 LiteLLM 的技术栈)——将 OpenAI/Anthropic 基础 URL 设为代理即可捕获流量;需要明确归因时,可添加 x-agenticledger-* 请求头。

原生支持 OTel 的工具(Gemini CLI、Codex [otel]、AutoGen/AG2、Pydantic AI、 Vercel AI SDK)无需使用代理——将其 OTLP 导出器指向 ledger,即可直接摄取 GenAI spans:

export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8000

支持两种 OTLP/HTTP 编码:始终支持 JSON;安装 [otel] 额外依赖后支持 protobuf(Docker 镜像已包含该依赖)。gRPC 导出器应切换到 HTTP:OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf。

框架指南——docs/integrations 中为每种集成都提供了指南:Claude Code、Codex CLI、 opencode、OpenClaw、BMAD-METHOD、LangGraph/LangChain、CrewAI、OpenAI Agents SDK、Gemini CLI、AutoGen/AG2、Pydantic AI、Vercel AI SDK、LiteLLM、 OpenRouter 和 LM Studio(完全离线:本地模型、本地 ledger)。

生产环境部署——TLS 终止、身份验证密钥、脱敏、镜像 签名/SBOM 验证、企业镜像源和扩展部署指南,请参阅 docs/deployment.md。


性能数据

实测结果,而非承诺。运行 python scripts/loadtest.py --calls 2000 --seed 1000000 即可复现(Apple M 系列 MacBook、SQLite 后端;在 0.10 版本的提供方适配器架构就绪后重新测量——数据相同,两种架构下均为每秒 2,580 至 2,800 次调用):

项目结果
持续捕获吞吐量每秒代理 2,886 次调用
每次调用增加的延迟p50 为 10ms · p95 为 12ms
直接写入存储约每秒 38,000 次保存
磁盘上存储一百万次调用271 MB
打开一个包含一百万次调用的会话2 ms
列出包含一百万次调用的会话335 ms
包含一百万次调用的 30 天报告719 ms

坦诚说明局限:每次加载都会汇总所有会话,因此会话列表耗时随历史记录总量增长;报告时间窗口使用时间戳索引,因此耗时随窗口内的流量增长,而非随表的大小增长。Agent 提供方的延迟(每次调用数百毫秒)比代理开销高出一个数量级。Postgres 的数据因服务器而异;同一脚本也可以通过 --dsn 测量。成本计算设有独立的保护机制,并会每五分钟与提供方控制台进行一次一致性检查:详见 docs/accuracy.md。

捕获的内容

每次大模型调用都会存储以下内容:

字段内容
action_id拦截时分配的 UUID
session_id运行分组(来自标头)
timestamp调用时间
model_id使用的模型
provideropenai 或 anthropic
messages发送给模型的完整消息历史
system_prompt提取的系统提示词
tools模型可用的工具定义
tool_calls模型决定调用的工具
tool_results工具返回的内容(来自下一次调用的消息)
content模型的文本输出
stop_reason模型停止的原因
tokens_in / tokens_outToken 用量
cache_read_tokens / cache_write_tokens提示词缓存用量——读取和写入会按各提供方的定价正确计费
thinking扩展思考输出(Anthropic),与 content 分开捕获
cost_usd根据模型定价估算的成本
latency_ms端到端响应时间
status_code上游 HTTP 状态——错误也会被捕获
error_detail非 200 响应的上游错误消息
agent_name来自 x-agenticledger-agent-name;否则自动检测(例如 claude-code);否则使用 OpenRouter 的 X-Title;再否则根据 Agent 自身指令生成 unnamed-<fingerprint>,以便区分未设置标头的 Agent
framework来自 x-agenticledger-framework 标头,或通过指纹检测(例如 claude-code、gemini-cli、litellm)
user_id来自 x-agenticledger-user-id 标头
app_id来自 x-agenticledger-app-id 标头
environment来自 x-agenticledger-environment 标头
parent_action_id嵌套 Agent 图中的父调用
handoff_from / handoff_toFlow DAG 的 Agent 交接跟踪

除了模型调用之外,会话还可以记录 Agent 自身的活动:agenticledger connect claude-code --hooks 会安装 Claude Code hooks,将 Agent 在其机器上的操作(运行的工具及其输入、输出和持续时间,请求或拒绝的权限、子 Agent、上下文压缩、会话开始和结束)发送到 /v1/hooks/claude-code。这些记录会显示在会话的 Activity 选项卡中,可在托管网关后使用,且绝不会用于引导 Agent。


API 参考

MethodEndpointDescription
GET/health存活状态 - {"status":"ok","version":"..."}。无需认证,绝不访问存储。
GET/readyz就绪状态 - 对存储执行 ping;无法连接时返回 503。同时报告 capture_dropped。
GET/metricsPrometheus 指标(已持久化/丢弃的捕获数量、队列深度)。
GET/api/audit敏感操作的审计记录,按时间从新到旧排列,采用哈希链;可按 action、actor、target、since、until 筛选,并使用 before_seq 分页(管理员)。
GET/api/audit/verify遍历审计哈希链,并指出第一个断点(如有)(管理员)。
DELETE/api/users/{user_id}删除权:删除某用户的所有已捕获调用(管理员)。
GET/实时仪表板
WS/wsWebSocket 流 - 为实时仪表板更新提供支持
GET/api/sessions会话及其汇总统计,按时间从新到旧排列。使用 limit(1 到 500,默认 50)和 offset 分页;使用 project(名称、__starred__ 或 run:<id>)、run_id、model、since、until(ISO 格式,基于最后一次调用)和 q(ID、标签或 Agent)筛选。X-Total-Count 和 X-Next-Offset 响应头会说明剩余内容。
GET/api/runs循环运行(显式指定或自动推断),包含迭代次数、成本、状态和已标记调用数,按时间从新到旧排列。分页方式和响应头相同;可使用 project、status(running、flagged、complete、ended、stopped)、model、since、until、q(ID 或标签)筛选。
GET/api/runs/{run_id}单次运行的状态(running / flagged / complete / ended / stopped)- 可在循环脚本中轮询此接口
POST/api/stop停止所有调用:全局紧急停止。每次大模型调用(包括重放)都会被立即拒绝并记录,直到解除停止;重启后仍然有效(编辑者)。DELETE 可解除停止,GET 可查看由谁以及何时启用了停止。
GET/api/sessions/{session_id}/tools派生的工具执行记录 - 每次工具调用都会与其结果、延迟和错误状态配对
GET/api/sessions/{session_id}/loop-block查询循环断路器是否正在拦截某个会话,以及拦截原因。DELETE 可在不重启的情况下解除拦截,并从此刻起重新启用防护(编辑者)。
DELETE/api/sessions/{session_id}删除一个会话及其所有调用
GET/api/reports?days=30支出洞察:每日趋势、模型构成及已核实的缓存节省额、延迟百分位数、按 Agent 和团队统计的总额
GET/api/whatif?model=...&run_id=...使用另一模型重新计算某次运行/会话/调用的已捕获令牌费用 - 纯数学计算,不调用 API
POST/api/tokens签发限定范围的 API 令牌 - 包括带有 budget_daily 及其专属 allow_models / deny_models / allow_providers / deny_providers 列表的 role: ingest 团队卡片
GET/api/calls/{action_id}按 ID 获取单次调用 - 沿重放记录的父级追溯到原始调用
GET/api/replay/targets已配置的重放目标(为仪表板下拉菜单提供数据)
GET/api/replay/models重放目标实际提供的模型(?provider=)
GET/auth/status查看此处是否已配置登录、提供方名称以及登录入口。无需认证。
GET/auth/login开始通过身份提供方登录(使用 ?next=/app#/runs 可返回指定位置)
POST/auth/logout结束本次登录并清除 Cookie
GET/api/people所有已登录用户,以及其所属组授予的角色和当前登录数量(管理员)
POST/api/people/{id}/signout立即结束某人的所有登录(管理员)
POST/api/ws/ticket为实时 /ws 套接字签发有效期一分钟、仅可使用一次的票据,密钥通过请求头发送(查看者)
GET/api/whoami我持有的密钥是什么?名称、角色和团队(适用于团队卡片)- 仪表板的 ⚿ 面板会使用此接口
POST/api/replay/batch使用另一模型重放整个运行或会话 - 返回作业 ID
GET/api/replay/jobs/{job_id}批量处理进度和报告卡
PUT/api/labels/{scope}/{ref_id}为会话/运行命名、置顶或归入某个项目;使用图标选择器固定列表中的 icon 和 color 标记("" 可清除任一项)
GET/api/projects当前使用的项目名称
GET/api/settings代理当前使用的配置(管理员;密钥已隐藏),每行均附有设置该配置的键及其可选值
GET / PUT/api/config当前生效的配置文件及其值(密钥已隐藏);PUT {key, value} 可写入一个键(null 表示清除),操作会记入审计日志,重启后生效(管理员)
POST/api/restart原地重启账本,以重新读取配置文件(管理员)
GET/api/runs/{run_id}/cache-audit此次运行符合资格并实际获得的重复折扣:判定、原因、修复方法、准确折扣额及标注估算值
POST/api/redetect对尚未归属的历史记录重新运行框架检测;返回检查数、更新数和各框架的计数
POST/api/replay重新执行一次已捕获调用 - 使用同一提供方,或转换到另一提供方(model 和可选的 provider);结果会与原始调用关联并存储
GET/api/search?q=...在所有已捕获调用中进行全文搜索
GET/session/{session_id}会话中的所有调用,按时间排序
GET/explain/{action_id}按操作 ID 查询单次调用
GET/export/{session_id}包含 SHA-256 完整性哈希的 JSON 合规性导出
GET/export/{session_id}/report可打印的 HTML 审计报告
POST/mcpMCP 工具服务 - list_sessions、explain、get_session、search、list_runs、get_run_status
POST/v1/tracesOTLP/HTTP JSON 接收 - 来自原生支持 OTel 的工具的 GenAI spans 会成为账本调用(/v1/logs 也会将 Claude Code 工具事件接收为工具耗时;/v1/metrics 会返回确认)
示例:
# All calls in a session
curl http://localhost:8000/session/run-1

# Search across all sessions
curl "http://localhost:8000/api/search?q=failed+to+connect"

# Download JSON audit trail (includes an integrity tag; keyed HMAC when configured)
curl http://localhost:8000/export/run-1 -o audit-run-1.json

# Printable HTML report - open in browser, print to PDF
open http://localhost:8000/export/run-1/report

MCP 服务

Agentic Ledger 会在 POST /mcp 提供一个 MCP(Model Context Protocol)工具服务,用于公开其捕获的数据。将 Claude Desktop、Cursor 或任何兼容 MCP 的客户端指向该服务,即可通过 AI 助手直接查询跟踪记录。

可用工具:

工具描述
list_sessions列出最近的会话,并汇总费用、令牌数和调用次数
explain(action_id)单次 LLM 调用的完整跟踪记录——提示词、工具调用、输出、令牌数、费用
get_session(session_id)按时间顺序列出一个会话中的所有调用
search(query)对所有捕获的调用进行全文搜索
list_runs列出循环运行及其迭代次数、费用和状态
get_run_status(run_id)查看一次运行的状态——让 Agent 检查自身循环并决定是否继续

在 claude_desktop_config.json 中配置(HTTP,连接到正在运行的代理):

{
  "mcpServers": {
    "agenticledger": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

或作为 stdio 子进程运行——适用于将服务作为命令启动的客户端 (无需运行中的代理;读取同一个数据库):

{
  "mcpServers": {
    "agenticledger": {
      "command": "agenticledger",
      "args": ["mcp"],
      "env": { "AGENTICLEDGER_DSN": "sqlite:////absolute/path/to/agenticledger.db" }
    }
  }
}

如果设置了 AGENTICLEDGER_API_KEY,请将其作为标头传递:

{
  "mcpServers": {
    "agenticledger": {
      "url": "http://localhost:8000/mcp",
      "headers": { "x-agenticledger-api-key": "your-key" }
    }
  }
}

连接后,你可以向助手询问以下内容:

  • “SearchAgent 在上一次会话中做了什么?”
  • “显示所有提到速率限制错误的调用。”
  • “会话 run-abc123 的总费用是多少?”

配置参考

以下每个变量也可以写入 agenticledger.toml——关于配置文件、搜索顺序和环境变量始终优先规则,请参阅 配置。

环境变量

核心:

变量必填默认值描述
AGENTICLEDGER_TELEMETRY_CALLS否(off)将 Claude Code 自身的 api_request 遥测(发送到 /v1/logs)记录为调用:模型、令牌、缓存、费用、延迟,不包含提示词。适用于托管设置使代理不在请求路径中的机器;参见 Claude Code 指南。代理位于请求路径中时请保持关闭。
AGENTICLEDGER_BEDROCK_GATEWAY_URL否(none)公司的 Bedrock 网关。Bedrock 格式的调用会按 Agent 发送时的原样转发到该网关,包括标头;账本不会签名,也不需要 AWS 凭证。
AGENTICLEDGER_UPSTREAM_URL否(unset: route by call format)要转发请求到的 LLM 端点。接受 OpenAI、Anthropic、LiteLLM、OpenRouter 或任何兼容 OpenAI 的 URL。省略此项时,代理会根据每次调用的线缆格式进行路由:Anthropic 格式的调用发往 Anthropic,Bedrock 路径发往 Bedrock,其余发往 OpenAI。
AGENTICLEDGER_TLS否(off)设为 1 时,会添加仅供仪表板使用的 https 监听器,并生成自签名证书(手机会警告一次)。Agent 端口仍使用普通 http。
AGENTICLEDGER_TLS_PORT否8443https 仪表板监听器的端口。
AGENTICLEDGER_DSN否sqlite:///agenticledger.db(Docker:sqlite:////data/agenticledger.db)数据库。本地开发使用 SQLite,生产环境使用 Postgres URL。
AGENTICLEDGER_HOST否0.0.0.0绑定的主机。使用 127.0.0.1 可将访问限制为仅限本地主机。
AGENTICLEDGER_PORT否8000运行端口。
AGENTICLEDGER_API_KEY否(none)管理员主密钥。设置后,仪表板、读取和管理端点都需要身份验证;此密钥授予 admin 角色,并用于引导 API 令牌(见下文)。本地开发时可跳过;代理运行在服务器上时请设置,密钥值由你自行选择。
AGENTICLEDGER_OIDC_ISSUER / _CLIENT_ID / _CLIENT_SECRET否(none)使用身份提供商登录(OpenID Connect,采用带 PKCE 的授权码流程)。_ROLE_MAP(group=role,...)用于决定角色;未映射的用户会被拒绝。_GROUPS_CLAIM(groups)、_SCOPES、_PROVIDER_NAME 均为可选项。重定向使用 AGENTICLEDGER_PUBLIC_URL。
AGENTICLEDGER_OIDC_SCOPE_MAP否(none)group=project,...(组可以重复):映射组中的用户只能看到指定项目,在账本读取数据的所有位置均如此;未归档的工作对他们不可见。不属于任何映射组的用户不受范围限制。
AGENTICLEDGER_SESSION_IDLE_HOURS / _MAX_HOURS否12 / 168登录会话的有效时长:空闲时限和绝对时限。
AGENTICLEDGER_INGEST_KEY否(none)设置后,代理只有在请求携带匹配的 x-agenticledger-ingest-key 标头时才会转发请求,从而关闭开放中继。默认关闭;未设置时,启动时会发出醒目的警告。
AGENTICLEDGER_REPLAY_API_KEY否(none)通过代理自身的上游进行同提供商重放所需的密钥——代理从不存储 Agent 凭证,因此重新执行需要单独提供密钥。
AGENTICLEDGER_REPLAY_OPENAI_KEY / _URL否(none) / 提供商 API跨提供商重放目标:在 OpenAI 格式的模型上重放任意捕获记录。将 _URL 指向 LM Studio(http://localhost:1234,密钥可任意填写),即可在本地模型上免费重放捕获的 Claude 调用。
AGENTICLEDGER_REPLAY_ANTHROPIC_KEY / _URL否(none) / 提供商 APIClaude 模型的跨提供商重放目标。
AGENTICLEDGER_*_KEY_FILE否(none)上述每个密钥也会从其 _FILE 变体指定的文件中读取,这是 Docker secrets 模式,可避免密钥留在 Shell 历史记录中。
AGENTICLEDGER_EXPORT_HMAC_KEY否(none)设置后,合规性导出会包含防篡改的带密钥 hmac-sha256 完整性标记,而非普通的 sha256 校验和。
AGENTICLEDGER_EXTRA_PATHS否(none)要捕获的其他请求路径,以逗号分隔,例如 v1/responses,v1/custom。内置路径(v1/chat/completions、v1/messages、v1/responses,以及记录为免费调用的 v1/messages/count_tokens)始终会被捕获。
AGENTICLEDGER_ASYNC_CAPTURE否off在后台工作线程中持久化捕获记录,使存储操作不会增加 Agent 调用的延迟。权衡之处:读取结果会最终一致(刚捕获的调用可能需要短暂等待才能查询到)。建议高吞吐场景使用。
AGENTICLEDGER_CAPTURE_QUEUE_MAX否10000异步模式下,在削减负载前缓冲的最大捕获记录数(丢弃数量会计入 /metrics)。
AGENTICLEDGER_CAPTURE_LEVEL否fullfull 会存储所有内容;metadata 仅存储指标/元数据(模型、令牌、费用、延迟、Agent、状态),并丢弃提示词、响应和工具。
AGENTICLEDGER_REDACT否(off)对存储的数据中的个人身份信息/机密进行脱敏:设为 all,或使用以逗号分隔的列表 email,ssn,credit_card,ip,api_key。匹配内容会替换为 [REDACTED:<label>]。仅影响存储的副本,不会更改 Agent 的响应。
AGENTICLEDGER_REDACT_PATTERNS否(none)额外的脱敏正则表达式,使用 JSON 格式:{"label": "regex", ...} 或 ["regex", ...]。
AGENTICLEDGER_RETENTION_DAYS否(永久保留)通过后台清理工作线程删除早于 N 天的捕获调用。
AGENTICLEDGER_AUDIT_LOG否on记录审计跟踪,追踪谁查看、导出或删除了哪些内容,以及令牌/擦除操作、登录失败、被拒绝的摄取凭证和 MCP 读取。设为 0 可禁用。
AGENTICLEDGER_AUDIT_STRICT否off如果审计日志无法记录某项操作,则拒绝该操作(HTTP 503)。关闭时,写入失败会被计数(agenticledger_audit_dropped_total)并记录日志,操作仍会继续。
AGENTICLEDGER_AUDIT_HMAC_KEY否(none)使用 HMAC-SHA256 为审计哈希链设置密钥。若不设置,哈希链将使用普通 SHA-256:可以检测到编辑,但拥有数据库访问权限的写入者可以重新生成哈希链。接受 _FILE 变体。
AGENTICLEDGER_AUDIT_STDOUT否off还会将每条审计记录作为一行 JSON 输出到 stdout,供日志抓取器和 SIEM Agent 使用。配置了 OTel 导出后,记录也会作为 OTLP 日志记录发送。
费用预算 - 阻止超出支出限额的调用(返回 HTTP 429):
变量默认值描述
AGENTICLEDGER_BUDGET_SESSION(none)每个 session_id 在其整个生命周期内的最高美元金额。
AGENTICLEDGER_BUDGET_AGENT(none)每个日历日(UTC)每个 agent_name 的最高美元金额。
AGENTICLEDGER_BUDGET_DAILY(none)每个日历日(UTC)所有调用的美元总额上限。
AGENTICLEDGER_BUDGET_USER(none)每个日历日(UTC)每个 user_id 的最高美元金额——跨会话跟踪用户。
AGENTICLEDGER_BUDGET_STATUS429预算限制触发时的 HTTP 状态码。429 会附带准确的 Retry-After(距 UTC 午夜窗口重置的秒数);如果客户端会激进地重试 429,可设为 402——不会有请求重试 Payment Required。
AGENTICLEDGER_BUDGET_ACTIONblock超出预算时的处理方式:block 返回 HTTP 429(调用不会到达大模型),warn 允许调用通过并触发 webhook 警报,both 则阻止调用并触发 webhook。
AGENTICLEDGER_BUDGET_UNPRICEDallow无法统计价格包中未定价模型的费用。allow 会以未知成本记录该模型(绝不记为 $0),允许未计费调用通过,并在日志中注明该模型;当任何预算生效时,refuse 会拒绝该调用。

并发情况下,预算和单次运行上限仍然有效。每个获准的调用都会预留一笔估算费用(文本按每个 token 四个字符计算,再加上其 max_tokens,并按普通调用的方式计价),直到记录实际费用为止。因此,一批并行调用无法各自占用同一份剩余额度。只有触及上限的那一次调用仍会通过,因为总会有一个调用先行,因此超支最多不超过一次调用的费用。调用费用一经记录、调用失败、被丢弃或被拒绝,预留金额就会立即释放。

允许列表和拒绝列表 - 在消耗任何配额之前拒绝模型或提供商(返回 HTTP 403 并注明规则,因此 Agent 会停止而不是重试)。匹配模式采用 shell glob,且不区分大小写。拒绝规则优先于允许规则;如果设置了允许列表,则只允许其中列出的内容。团队卡片可以包含相同的四个列表(参见团队卡片——一个代理,多个团队);整个服务群的列表始终生效,卡片只能进一步缩小范围。

变量默认值描述
AGENTICLEDGER_ALLOW_MODELS(none)以逗号分隔的模型匹配模式,例如 claude-*,gpt-4o。设置后,只有匹配的模型才能通过。
AGENTICLEDGER_DENY_MODELS(none)直接拒绝的模型匹配模式,例如 *-preview。
AGENTICLEDGER_ALLOW_PROVIDERS(none)提供商名称或匹配模式(openai、anthropic、bedrock、azure-openai)。设置后,只有这些提供商才能通过。
AGENTICLEDGER_DENY_PROVIDERS(none)直接拒绝的提供商。

速率限制 - 阻止超出请求频率限制的调用(返回 HTTP 429,采用滑动的 60 秒窗口)。每次拒绝都会作为琥珀色的 blocked: 行记录,并附带原因;它们会按会话和团队计入 Reports 及 /metrics(agenticledger_refusals_total{reason=...}),这样重试风暴会清晰可见,而不会悄然消失:

变量默认值描述
AGENTICLEDGER_RATE_LIMIT_RPM(none)全局每分钟最大请求数。
AGENTICLEDGER_RATE_LIMIT_SESSION_RPM(none)每个 session_id 每分钟最大请求数。
AGENTICLEDGER_RATE_LIMIT_AGENT_RPM(none)每个 agent_name 每分钟最大请求数。
AGENTICLEDGER_RATE_LIMIT_USER_RPM(none)每个 user_id 每分钟最大请求数。

循环引擎 - 每次调用都会串联到 ReAct 线程(thread_id、step_index、prev_action_id)中,并将新上下文循环迭代分组到各次运行中,同时检测卡住的循环:

变量默认值说明
AGENTICLEDGER_LOOP_ACTIONwarnwarn 会记录 loop_flags 并触发 loop_flag webhook 警报;block 还会对触发防护规则的会话返回 HTTP 429(loop_detected),记录每次拒绝,并可在仪表板中从会话页面解除限制,无需重启(DELETE /api/sessions/{id}/loop-block;防护规则会从解除限制的位置重新启用);off 会禁用推断。
AGENTICLEDGER_LOOP_REPEAT_THRESHOLD3在将线程标记为卡住之前,允许连续出现的相同工具调用次数(工具和参数均相同)。
AGENTICLEDGER_LOOP_MAX_STEPS(none)将超过此 ReAct 步数的线程标记为异常(在 block 模式下会停止线程)。
AGENTICLEDGER_LOOP_RUN_GAP_SECONDS900新上下文派生之间的最大间隔(系统提示词相同),在此间隔内仍计为同一次运行的迭代。
AGENTICLEDGER_COMPLETION_PROMISE(none)与响应文本匹配的正则表达式。匹配时,该调用会被标记为 completion_promise,运行状态会变为 complete——循环运行器会轮询 GET /api/runs/{run_id} 并停止。

警报 - 达到阈值时向你的 webhook 发送 POST 请求(不会阻止调用——参见警报):

变量默认值说明
AGENTICLEDGER_ALERT_WEBHOOK_URL(none)用于 POST 警报负载的 URL。触发任何警报都需要此项。Slack、Discord 和 PagerDuty URL 会使用其原生格式。
AGENTICLEDGER_ALERT_FORMATauto负载格式:auto 根据 webhook 主机判断;generic、slack、discord 或 pagerduty 可强制指定格式。
AGENTICLEDGER_ALERT_PAGERDUTY_KEY(none)PagerDuty Events v2 集成密钥;当 webhook 为 events.pagerduty.com 时需要。接受 _FILE 变体。
AGENTICLEDGER_PUBLIC_URL(none)仪表板的访问地址(https://ledger.example.com),以便有关运行或会话的通知包含指向它的链接。
AGENTICLEDGER_DIGEST_HOUR(off)每日支出摘要的 UTC 小时(0-23);摘要包含过去 24 小时的总额、缓存节省金额和使用量最高的模型/Agent,并会 POST 到警报 webhook。兼容 Slack incoming webhook(text)。
AGENTICLEDGER_ALERT_COST_PER_CALL(none)单次调用费用超过 $X 时发出警报。
AGENTICLEDGER_ALERT_LATENCY_MS(none)单次调用耗时超过 Xms 时发出警报。
AGENTICLEDGER_ALERT_ERROR_RATE(none)会话错误率超过 X 时发出警报(例如,0.5 = 50%)。
AGENTICLEDGER_ALERT_DAILY_SPEND(none)每日支出超过 $X 时发出警报。与预算不同,此项不会阻止调用。

OpenTelemetry - 向任何兼容 OTLP 的收集器发送 spans(需要 pip install "agentic-ledger[otel]"——参见 OpenTelemetry 导出):

变量默认值说明
AGENTICLEDGER_OTEL_ENDPOINT(none)OTLP/HTTP 基础 URL,例如 http://localhost:4318。未设置时会禁用 OTel 导出。
AGENTICLEDGER_OTEL_SERVICE_NAMEagenticledger向收集器报告的 service.name 值。
AGENTICLEDGER_OTEL_HEADERS(none)以逗号分隔的 key=value 身份验证标头,例如 x-honeycomb-team=abc123。

定价覆盖 - 覆盖或扩展内置的每 Token 定价表(启动时合并):

变量默认值说明
agenticledger pricing update从仓库获取当前价格包并存入 ~/.agenticledger/pricing/(下次启动时覆盖内置定价)。只有运行此命令时才会访问网络(agenticledger upgrade 也一样);程序不会自行向外发送数据。
AGENTICLEDGER_PRICING(none)内联 JSON 映射,包含 model → [input_per_million, output_per_million](单位为 USD)。例如:'{"gpt-4o": [2.50, 10.00], "my-model": [1.00, 2.00]}'。
AGENTICLEDGER_PRICING_FILE(none)相同格式的 JSON 文件路径。应用顺序在 AGENTICLEDGER_PRICING 之后。

常见启动示例
# Local dev - OpenAI (default)
AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com uv run python -m agenticledger.proxy

# Local dev - Anthropic
AGENTICLEDGER_UPSTREAM_URL=https://api.anthropic.com uv run python -m agenticledger.proxy

# Local dev - LiteLLM gateway (any model)
AGENTICLEDGER_UPSTREAM_URL=http://localhost:4000 uv run python -m agenticledger.proxy

# Production - Postgres + auth + budgets + rate limits + alerts
AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com \
AGENTICLEDGER_DSN=postgresql://user:password@localhost/agenticledger \
AGENTICLEDGER_API_KEY=my-secret \
AGENTICLEDGER_BUDGET_DAILY=20.00 \
AGENTICLEDGER_BUDGET_SESSION=2.00 \
AGENTICLEDGER_RATE_LIMIT_SESSION_RPM=20 \
AGENTICLEDGER_RATE_LIMIT_USER_RPM=60 \
AGENTICLEDGER_ALERT_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz \
AGENTICLEDGER_ALERT_COST_PER_CALL=0.50 \
AGENTICLEDGER_ALERT_DAILY_SPEND=15.00 \
uv run python -m agenticledger.proxy

设置 AGENTICLEDGER_API_KEY 后,请在请求头中传入该密钥,以访问受保护的端点:

curl -H "x-agenticledger-api-key: my-secret" http://localhost:8000/session/run-1

密钥只能通过请求头传递。若将密钥放在查询字符串中(?api_key=、?token=),请求会被拒绝,并返回说明原因的 401 响应:URL 会出现在访问日志、代理日志、浏览器历史记录和 Referer 请求头中。在浏览器中,将密钥粘贴到仪表板的 ⚿ 面板,或者打开 agenticledger share 生成的配对链接。该链接会将密钥放在 # 后面(即 URL 片段中,浏览器绝不会将其发送给任何服务器)。

使用你的身份提供商登录(OpenID Connect)

此功能面向用户,而非脚本:将账本连接到你的身份提供商后,⚿ 面板会显示一个 使用 Okta 登录 按钮(或者显示你为其指定的名称)。系统通过 PKCE 授权码流程进行身份验证,根据身份提供商的密钥验证 ID 令牌(RS256),并根据用户所属的组确定其角色:如果某人的组没有匹配项,系统会拒绝其访问、告知原因并记录此事。密钥仍可同时使用,供 Agent 和脚本访问。

AGENTICLEDGER_OIDC_ISSUER=https://your-org.okta.com
AGENTICLEDGER_OIDC_CLIENT_ID=0oa...
AGENTICLEDGER_OIDC_CLIENT_SECRET_FILE=/run/secrets/oidc   # omit for a public client
AGENTICLEDGER_OIDC_ROLE_MAP=ledger-admins=admin,ledger-editors=editor,ledger-viewers=viewer
AGENTICLEDGER_PUBLIC_URL=https://ledger.example.com          # the redirect back lands here

在身份提供商中,将 https://ledger.example.com/auth/callback 注册为重定向 URI。登录状态保存在服务器端,浏览器通过 Cookie 持有该状态(httponly、SameSite=Lax,通过 https 传输时为 Secure);闲置 12 小时或达到 7 天后(AGENTICLEDGER_SESSION_IDLE_HOURS、AGENTICLEDGER_SESSION_MAX_HOURS)、用户退出登录,或管理员结束会话(POST /api/people/{id}/signout)时,登录状态会失效。通过 Cookie 发起的所有修改请求都必须来自仪表板自身的源。每条审计记录都会注明用户的电子邮件地址。GET /api/people 会列出已登录用户及其角色和所属组。

限定范围的访问。 AGENTICLEDGER_OIDC_SCOPE_MAP=team-alpha=alpha,team-alpha=alpha-infra 会让 team-alpha 组中的所有人只能查看指定项目:项目列表、单个会话和运行、搜索、报告、导出、假设分析、回放以及 MCP 工具都仅在此范围内返回结果;范围外的内容会显示为未找到。归档到任何项目之外的工作对受限用户不可见,直到有人为其指定项目。未加入任何已映射组的用户不受范围限制,可像以前一样查看其角色允许的所有内容。受限编辑者只能在所属项目中归档工作。

若要在没有身份提供商的情况下试用:agenticledger idp 会在回环地址上运行一个测试身份提供商,其中包含四个虚构用户(alice 是管理员,dave 不属于任何已映射组),打印需要设置的四行配置,并在每个页面上声明该服务不适用于生产环境。

受限范围的 API 令牌(RBAC)

主密钥使用方便,但权限划分较粗。若要为团队提供访问权限,可创建具有相应角色的受限范围、可撤销令牌,而不是共享主密钥。令牌是随机密钥,仅在创建时显示一次;系统只存储其 SHA-256 哈希值。

角色具有层级关系,但有一个例外:ingest 不属于此层级,只开放代理路径。

角色权限
ingest只能通过代理发送调用(团队卡片使用的就是此角色):每次调用都会归属到相应团队,并计入该团队的每日预算;无法读取仪表板、API、导出内容或 MCP
viewer读取已捕获的数据——仪表板、API、导出内容、MCP
editorviewer 的权限 + 删除会话
admineditor 的权限 + 管理 API 令牌
# Mint a viewer token (admin only - use the master key to bootstrap)
curl -X POST http://localhost:8000/api/tokens \
  -H "x-agenticledger-api-key: my-secret" \
  -H "content-type: application/json" \
  -d '{"name": "grafana-readonly", "role": "viewer", "expires_in_days": 90}'
# → {"token_id": "...", "token": "agl_…", "role": "viewer", ...}  (token shown once)

# Use it (Authorization: Bearer or the x-agenticledger-token header)
curl -H "Authorization: Bearer agl_…" http://localhost:8000/api/sessions

# List and revoke
curl -H "x-agenticledger-api-key: my-secret" http://localhost:8000/api/tokens
curl -X DELETE -H "x-agenticledger-api-key: my-secret" http://localhost:8000/api/tokens/<token_id>

只有设置了 AGENTICLEDGER_API_KEY 时才会强制执行身份验证;主密钥是用于创建令牌的管理员引导凭据。实时 /ws 数据流接受请求头(Authorization: Bearer 或 x-agenticledger-token)或票据:浏览器无法在 websocket 握手中添加请求头,因此仪表板会先在请求头中传入密钥,调用 POST /api/ws/ticket,然后通过 /ws?ticket=... 建立连接。该随机票据有效期为一分钟,且只能使用一次;使用后便失效。未通过身份验证的连接,以及任何在 URL 中包含密钥的连接,都会被拒绝,并返回关闭代码 1008。


请求标头

在每次调用 LLM 时,由你的 Agent 传递以下标头。所有标头均为可选。它们可以丰富捕获的数据、支持 Flow 选项卡,并启用按维度设置的预算和速率限制。

标头默认值描述
x-agenticledger-session-id(none)将一次运行中的所有调用归为一组。每次 Agent 执行都使用一致的 ID(例如 UUID 或 "run-1")。如果不设置,调用会被存储,但不会在仪表板中归为一组。
x-agenticledger-user-id(none)触发此次运行的最终用户。用于启用按用户设置的速率限制和审计。
x-agenticledger-agent-name(none)发起此次调用的 Agent 名称(例如 "orchestrator"、"researcher")。用于 Flow 选项卡中的 DAG,以及 Agent 级别的预算和速率限制。
x-agenticledger-app-id(none)应用名称或 ID。多个应用共用一个代理时,此项会很有用。
x-agenticledger-parent-action-id(none)派生出此次调用的调用的 action_id。设置后,Trace 选项卡会绘制明确的父子连接线。如果不设置,Trace 选项卡会根据时间戳自动推断关系。
x-agenticledger-environmentdevelopmentproduction、staging 或 development。会显示在仪表板中。
x-agenticledger-handoff-from(none)交出控制权的 Agent(例如 "orchestrator")。会在 Flow DAG 中显示为有向边。
x-agenticledger-handoff-to(none)接收控制权的 Agent(例如 "researcher")。会在 Flow DAG 中显示为有向边。
x-agenticledger-framework(auto-detected)发起此次调用的框架/工具(例如 "langgraph"、"bmad")。如果未设置,系统会自动识别知名客户端(Claude Code、Gemini CLI、LiteLLM)。
x-agenticledger-run-id(auto-inferred)将多个会话归为一次循环运行(例如一次 Ralph 通宵运行)。如果未设置,系统会自动将共享系统提示词、且使用新上下文的会话归为一组,前提是它们之间的间隔不超过 AGENTICLEDGER_LOOP_RUN_GAP_SECONDS。
x-agenticledger-iteration(auto-inferred)此次运行中的迭代编号。

单 Agent——完整注释:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="your-openai-key",
    default_headers={
        "x-agenticledger-session-id":  "run-abc123",
        "x-agenticledger-user-id":     "user-42",
        "x-agenticledger-agent-name":  "researcher",
        "x-agenticledger-app-id":      "my-app",
        "x-agenticledger-environment": "production",
    },
)

多 Agent 系统——跟踪控制权移交:

from openai import OpenAI

# Orchestrator
orchestrator_client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="your-openai-key",
    default_headers={
        "x-agenticledger-session-id":  "run-abc123",
        "x-agenticledger-agent-name":  "orchestrator",
    },
)

# Researcher (receives handoff from orchestrator)
researcher_client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="your-openai-key",
    default_headers={
        "x-agenticledger-session-id":   "run-abc123",
        "x-agenticledger-agent-name":   "researcher",
        "x-agenticledger-handoff-from": "orchestrator",
        "x-agenticledger-handoff-to":   "researcher",
    },
)

Flow 选项卡会将 orchestrator → researcher 呈现为 DAG,并在每个节点上显示成本和延迟。

OpenAI Agents SDK(openai-agents)——按 Agent 配置客户端:

openai-agents SDK 使用自己的内部 OpenAI 客户端。若要传递 Agentic Ledger 标头,你需要使用 OpenAIResponsesModel 为每个 Agent 创建一个客户端,并将其设为该 Agent 的 model。

import uuid
import os
from openai import AsyncOpenAI
from agents import Agent
from agents.models.openai_responses import OpenAIResponsesModel

SESSION_ID = f"run-{uuid.uuid4().hex[:8]}"  # one per execution
BASE_URL = os.getenv("OPENAI_BASE_URL")      # e.g. http://localhost:8000/v1

def al_model(agent_name: str, model: str = "gpt-4o-mini",
             handoff_from: str | None = None, handoff_to: str | None = None):
    """Create a model instance that sends Agentic Ledger metadata headers."""
    if not BASE_URL:
        return model  # proxy not configured - use default client
    headers = {
        "x-agenticledger-session-id": SESSION_ID,
        "x-agenticledger-agent-name": agent_name,
    }
    if handoff_from:
        headers["x-agenticledger-handoff-from"] = handoff_from
    if handoff_to:
        headers["x-agenticledger-handoff-to"] = handoff_to
    client = AsyncOpenAI(base_url=BASE_URL, api_key=os.getenv("OPENAI_API_KEY", ""),
                         default_headers=headers)
    return OpenAIResponsesModel(model=model, openai_client=client)

planner = Agent(name="PlannerAgent", model=al_model("PlannerAgent", handoff_to="SearchAgent"), ...)
searcher = Agent(name="SearchAgent",  model=al_model("SearchAgent",  handoff_from="PlannerAgent", handoff_to="WriterAgent"), ...)
writer   = Agent(name="WriterAgent",  model=al_model("WriterAgent",  handoff_from="SearchAgent",  handoff_to="EmailAgent"), ...)
emailer  = Agent(name="EmailAgent",   model=al_model("EmailAgent",   handoff_from="WriterAgent"), ...)

每个 Agent 的调用都会标记其名称和在流水线中的位置。Flow 选项卡会自动呈现完整的 PlannerAgent → SearchAgent → WriterAgent → EmailAgent DAG。

为何使用按 Agent 配置的客户端? set_default_openai_client() 会设置一个全局客户端——这适用于单 Agent 应用,但在多 Agent 系统中,无法为每个 Agent 传递不同的 agent_name 或 handoff_* 标头。正确的做法是为每个 Agent 创建单独的 OpenAIResponsesModel 实例。


告警

当阈值被突破、循环被标记、运行遇阻或运行结束时,Agentic Ledger 会向你的 webhook URL 发送通知。系统会根据 URL 识别 Slack incoming webhooks、Discord webhooks 和 PagerDuty Events v2,并采用它们原生的格式(可通过 AGENTICLEDGER_ALERT_FORMAT 覆盖);其他 URL 则会收到下面的纯 JSON。

可靠性由设计保证。 每条通知都会在请求路径之外尝试发送三次,并采用退避间隔(1 秒、3 秒、9 秒);每个时间窗口只通知一次(每日预算超出时每天通知一次,循环被标记时每十分钟通知一次,运行遇阻时每小时通知一次);所有通知都会被记录:设置页面会列出已发送的通知、是否成功送达、尝试次数以及失败原因,并提供发送测试通知按钮,让你只需点击一次即可接入 Slack。GET /api/notifications 会返回相同的历史记录。设置 AGENTICLEDGER_PUBLIC_URL 后,每条与运行或会话相关的通知都会附带直达链接。

负载格式(纯 JSON;原生格式包含相同信息):

{
  "type":       "high_cost",
  "message":    "Single call cost $0.1842 exceeded threshold $0.10",
  "value":      0.1842,
  "threshold":  0.10,
  "action_id":  "a1b2c3d4-...",
  "session_id": "run-1",
  "agent_name": "researcher",
  "timestamp":  "2026-04-03T12:00:00+00:00"
}

告警类型:

类型触发条件
high_cost单次调用超过 AGENTICLEDGER_ALERT_COST_PER_CALL
high_latency单次调用耗时超过 AGENTICLEDGER_ALERT_LATENCY_MS
high_error_rate会话错误率超过 AGENTICLEDGER_ALERT_ERROR_RATE
daily_spend每日总支出超过 AGENTICLEDGER_ALERT_DAILY_SPEND
budget_exceeded达到预算上限,且 AGENTICLEDGER_BUDGET_ACTION 为 warn 或 both
run_ceiling_approaching运行支出达到其费用上限的 80%(每次运行仅触发一次)
loop_flag循环引擎在某次调用上标记了问题(repeat_tool_call、step_budget_exceeded、completion_promise)
run_complete检测到运行完成承诺——负载包含完整的运行摘要(迭代次数、费用、令牌数、被标记的调用)
run_ended运行进入静默状态(在运行间隔内没有调用)——发送相同的摘要,因此隔夜循环结束后,第二天早上你就能在频道中看到通知
run_failed运行进入静默状态,且最后一次迭代以错误结束——发送相同的摘要,并标记为失败
run_blocked运行的调用在拦截边界被拒绝(熔断开关、费用上限、预算、停止所有调用、模型列表或提供商列表)——每次运行及原因每小时通知一次,并附上原因
test你点击了“发送测试通知”
团队卡片——一个代理,多个团队

把它想成额度卡:你保留唯一的真实服务商密钥,并给每个团队发一张专属卡片。每张卡片都可以访问代理,为每次调用标记团队名称,还可以设置自己的每日预算——当市场营销团队达到 10 美元时,只有市场营销团队会被拦截(并收到如实的 Retry-After)。

curl -X POST http://localhost:8000/api/tokens \
  -H "x-agenticledger-api-key: $ADMIN_KEY" -H 'content-type: application/json' \
  -d '{"name": "marketing", "role": "ingest", "budget_daily": 10.00}'

响应只会显示一次卡片——账本只存储它的哈希值。团队使用 x-agenticledger-ingest-key 而不是共享密钥。Reports 会新增按团队划分的表格,显示每张卡片额度对应的错误、拦截次数和今日支出。使用 DELETE /api/tokens/{token_id} 撤销卡片,只会影响对应团队——从那一刻起,该卡片会收到最终的 403(“请求被拒绝”),Agent 会接受这一响应,不会引发重试风暴。如果误将卡片粘贴到仪表板的 ⚿ 面板中,系统会用直白的话告诉你:卡片用于访问中继,而不是仪表板。

卡片还可以为模型和服务商设置自己的允许列表和拒绝列表,作为全体配置 AGENTICLEDGER_ALLOW_MODELS 等规则的补充。全体列表始终生效;卡片只能进一步收窄范围,不能放行全体规则拒绝的模型。拒绝响应会指出规则和团队,并像其他拦截一样显示在按团队划分的表格中。

curl -X POST http://localhost:8000/api/tokens \
  -H "x-agenticledger-api-key: $ADMIN_KEY" -H 'content-type: application/json' \
  -d '{"name": "marketing", "role": "ingest", "budget_daily": 10.00,
       "allow_models": ["gpt-4o", "claude-sonnet-*"], "deny_providers": ["bedrock"]}'

预算与提醒:

  • 预算(AGENTICLEDGER_BUDGET_*)——在调用到达大模型之前拦截。Agent 会收到 HTTP 429。
  • 提醒(AGENTICLEDGER_ALERT_*)——调用会继续执行,之后你会收到通知。

Webhook 接收的内容。 每条提醒都会以一个 JSON POST 请求发送,使用我们自定义的字段名:type(见下表)、message、value、threshold、action_id、session_id、agent_name、timestamp。每日日报(AGENTICLEDGER_DIGEST_HOUR=8)会作为单独的 POST 请求发送,包含 type: daily_digest、可直接阅读的 text 区块(最近 24 小时的支出、缓存节省金额、热门模型和 Agent),以及 totals。

Slack——粘贴 Incoming Webhook URL(hooks.slack.com):每条通知都会以带标题的消息送达,包含详细信息和“在 Agentic Ledger 中打开”链接。

PagerDuty——使用 Events API v2 URL(https://events.pagerduty.com/v2/enqueue),并将 AGENTICLEDGER_ALERT_PAGERDUTY_KEY 设置为集成密钥:通知会触发事件,按类型设置严重级别(运行失败或被拦截时为严重,达到阈值时为警告,摘要和日报时为信息),并附带去重键和运行链接。

Discord——频道 Webhook URL(discord.com/api/webhooks/...):以带标题的嵌入式消息发送详细信息和链接。

自定义——任何可接受 JSON POST 请求的 HTTP 端点。


OpenTelemetry 导出

Agentic Ledger 可以将每次被拦截的 LLM 调用作为 OTel span 发送到任何兼容 OTLP 的收集器:Grafana Tempo、Jaeger、Honeycomb、Datadog、Dynatrace,或任何支持 OTLP/HTTP 的供应商。

安装额外依赖(Docker 镜像已包含 OTel,使用 Docker 时无需额外步骤):

pip install "agentic-ledger[otel]"
# or
uv add "agentic-ledger[otel]"

配置:

变量默认值描述
AGENTICLEDGER_OTEL_ENDPOINT(none)OTLP/HTTP 基础 URL,例如 http://localhost:4318。未设置时会禁用 OTel 导出。
AGENTICLEDGER_OTEL_SERVICE_NAMEagenticledger发出的资源中 service.name 的值。
AGENTICLEDGER_OTEL_HEADERS(none)以逗号分隔的 key=value 键值对,用于认证标头,例如 x-honeycomb-team=abc123,x-honeycomb-dataset=llm。

示例 - Grafana Tempo:

AGENTICLEDGER_UPSTREAM_URL=https://api.openai.com \
AGENTICLEDGER_OTEL_ENDPOINT=http://localhost:4318 \
AGENTICLEDGER_OTEL_SERVICE_NAME=my-agent \
uv run python -m agenticledger.proxy

示例 - Honeycomb:

AGENTICLEDGER_OTEL_ENDPOINT=https://api.honeycomb.io \
AGENTICLEDGER_OTEL_HEADERS=x-honeycomb-team=YOUR_API_KEY,x-honeycomb-dataset=llm-traces \
uv run python -m agenticledger.proxy

发出的 span 属性(GenAI 语义约定):

属性来源
gen_ai.system提供商(openai / anthropic)
gen_ai.operation.name始终为 chat
gen_ai.request.model模型 ID
gen_ai.request.temperature设置时提供
gen_ai.request.max_tokens设置时提供
gen_ai.usage.input_tokens输入 token 数
gen_ai.usage.output_tokens输出 token 数
gen_ai.response.finish_reasons停止原因
agenticledger.action_id唯一调用 ID
agenticledger.session_id运行分组
agenticledger.agent_name来自标头
agenticledger.user_id来自标头
agenticledger.cost_usd估算成本
agenticledger.latency_ms端到端延迟
agenticledger.environment来自标头
agenticledger.handoff_from / agenticledger.handoff_toAgent 交接
http.status_code上游 HTTP 状态码

Span 会按 session_id 分组为 trace——一个会话中的所有调用都会在后端显示为一条 trace。父子关系遵循 x-agenticledger-parent-action-id。错误 span(status_code != 200)会标记为 StatusCode.ERROR。


合规文档

如需进行安全或隐私审查:docs/compliance 包含数据流图、附有 DPA 附件的数据处理说明、子处理方声明(无:软件运行在安装位置,不会向项目发送任何内容)、HIPAA 立场、附有每项控制措施证据的 SOC 2 和 ISO 27001 控制映射,以及支持期限(最新次要版本会获得所有修复,前一个次要版本会在 90 天内获得安全修复)。这些材料可直接作为附件使用,并如实说明项目不持有的内容:没有 SOC 2 报告、没有 ISO 证书,也没有 BAA。

合规导出

每个会话都可以导出为带完整性标记的审计轨迹——适用于受监管行业、内部审计,或将 trace 传递给外部工具。

# Machine-readable JSON with an integrity tag over the calls array
curl http://localhost:8000/export/run-1 -o audit-run-1.json

# Printable HTML - open in browser and print to PDF
open http://localhost:8000/export/run-1/report

JSON 导出会为 calls 数组附加完整性标记。默认情况下,这是一个 sha256 校验和——它可以检测意外损坏,但不是签名(任何编辑 calls 的人都可以重新计算校验和)。设置 AGENTICLEDGER_EXPORT_HMAC_KEY 可切换为带密钥的 hmac-sha256 标记,以实现篡改可检测:持有密钥的接收方可以检测任何修改,并且没有密钥就无法伪造该标记。


发布

标记版本会自动触发完整的发布流水线:

git tag v0.2.0
git push origin v0.2.0

该流水线会运行三个任务:

  1. Docker - 为 linux/amd64 + linux/arm64 构建 ghcr.io/shekharbhardwaj/agentic-ledger:{version} 和 :latest,推送时附带 SBOM + provenance 证明,使用 Sigstore cosign(无密钥)对摘要签名,并在配置了 DOCKERHUB_USERNAME/DOCKERHUB_TOKEN 密钥时镜像到 Docker Hub
  2. PyPI - 使用可信发布(无需 API 令牌)构建并向 PyPI 发布 agentic-ledger=={version},附带 PEP 740 证明
  3. GitHub Release - 创建包含自动生成的变更日志的发布,并附上镜像 SBOM(SPDX)

首次设置 PyPI(仅需一次):

  1. 前往 pypi.org/manage/account/publishing
  2. 添加一个新的待处理发布者:
    PyPI project name:  agentic-ledger
    Owner:              ShekharBhardwaj
    Repository:         AgenticLedger
    Workflow name:      release.yml
    Environment name:   pypi
    
  3. 在 GitHub 中创建 pypi 环境:repo → Settings → Environments → New environment → 将其命名为 pypi
  4. 就这样——无需配置密钥

故障排除

从这里开始:agenticledger doctor。 一个命令就能全面检查 你的机器:PATH 上的每个安装及其覆盖关系、每个安装对应的 Python 以及是否能正常运行(通过真实的导入探测发现架构错误的 wheel 和缺失的依赖)、后台服务正在提供什么,以及针对每个问题的修复命令。下面 的大多数问题都可以通过它自行诊断。添加 --fix 后,它会应用列出的修复:使用各自解释器的 pip 移除相互覆盖的安装,添加建议的 PATH 前置项进行清理,然后再次运行诊断。

旧版本 / 命令或环境变量名为 agentledger(没有“ic”) - 你正在运行 0.4 之前的版本,很可能是因为虚拟环境中已经安装了 该软件包:直接运行 pip install agentic-ledger 会提示“requirement already satisfied”,并且不会升级。运行 agenticledger upgrade - 它会 使用拥有该安装的 Python 环境,因此无需猜测该用哪个 pip - 然后重启。代理会在启动时的第一行打印版本号,而 curl localhost:8000/health 也会报告版本号。从 0.4.0 开始,所有名称都统一为 agenticledger - 请参阅 CHANGELOG 中的迁移说明。

重放失败,提示 401“invalid x-api-key” - AGENTICLEDGER_REPLAY_API_KEY 需要来自 console.anthropic.com (或 platform.openai.com)的真实服务商 API 密钥。Claude Code 订阅登录不是 API 密钥,不能用于此处。没有密钥?可以通过本地模型免费进行重放 - 请参阅 LM Studio 指南。

macOS 上出现 incompatible architecture (have 'arm64', need 'x86_64') - 你的 终端正在 Rosetta 下运行,因此 Python 选择了 x86_64 切片,而 pip 安装的是 arm64 原生 wheel。运行 arch 检查(Apple Silicon 上应输出 arm64)。快速修复:在命令前加上 arch -arm64。永久修复: 取消勾选终端应用中的“Open using Rosetta”,使用 Apple Silicon 版本的编辑器, 并重启任何长期运行的 tmux 服务。

module 'httpx' has no attribute 'AsyncClient' - 已在 0.3.0-alpha.2 中修复;运行 pip install --upgrade agentic-ledger 升级。

端口 8000 已被占用 - 另一个代理实例(或应用)正在运行; 停止它或设置 AGENTICLEDGER_PORT。

Claude Code 返回 401 OAuth access token has expired - 代理 原样转发了 Anthropic 的响应;请通过 claude → /login 重新进行身份验证。出错的调用仍会被记录,因此你会在 仪表板中看到 401。

/ 返回 404“Web app not built” - 你正在未构建 Web 应用的 源码检出目录中运行。执行 cd dashboard-app && npm ci && npm run build,然后重启。PyPI 和 Docker 安装始终包含该应用。


许可证

MIT

mcp-name: io.github.ShekharBhardwaj/agentic-ledger

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。