关于 agentic-ledger
Agentic Ledger 是面向 AI Agent 运行的本地优先观测代理,适合需要检查活动和成本的开发者与团队。它记录请求和响应,并通过实时仪表板与 API 展示会话、循环活动、成本及重放。
主要功能
- 01通过代理捕获请求和响应
- 02跟踪会话、成本和循环运行
- 03检查调用轨迹、流程和详情
- 04将记录的运行重放到其他模型
- 05设置运行成本上限并阻止后续调用
适用场景
- 01调查 Agent 运行中的调用和提示词
- 02比较使用不同模型的记录运行
- 03为 Agent 循环设置支出上限
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Agentic Ledger
AI Agent 运行时可观测性——准确查看 Agent 做了什么、为何这么做,以及花费了多少。
这些数字应当与您的服务提供商账单一致。如果不一致,这就是我们希望您报告的错误。
适用于任何 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"
三条规则:
- 配置文件按以下顺序查找:
AGENTICLEDGER_CONFIG,然后是./agenticledger.toml(你启动命令时所在的文件夹),最后是~/.agenticledger/config.toml。使用第一个匹配项;启动横幅会显示 当前生效的文件。 - 命令中输入的任何内容都会覆盖文件中的设置。 环境变量会逐项覆盖设置(
AGENTICLEDGER_PORT=9000 agenticledger start会在本次运行中使用 9000, 不会修改文件)——这也是为什么通过环境变量配置的 Docker 和 CI 设置不受影响。 - 更改需重启后生效(先运行
agenticledger stop,再运行start)。
以下环境变量参考中的每项设置都有对应的配置文件选项;
[env] 部分会原样传递其他任何 AGENTICLEDGER_* 变量。
按步骤配置各提供商
以下所有提供商都使用同一个代理;唯一的变化是指向该代理的基本 URL。
每个配置示例都假设代理已启动(agenticledger start),并以同样的检查结束:发起一次调用,打开 http://localhost:8000,然后在 Sessions 中查看。
OpenAI(以及任何兼容 OpenAI 的 API)
- 将客户端指向代理:
export OPENAI_BASE_URL=http://localhost:8000/v1 - 保持
OPENAI_API_KEY原样不变——代理会原样传递你的 身份验证标头。 - 发起一次调用;它会带有 O 标记,显示在 Sessions 中。
Anthropic
- 将客户端指向代理:
export ANTHROPIC_BASE_URL=http://localhost:8000 - 保持
ANTHROPIC_API_KEY原样不变。 - 发起一次调用;它会带有 A 标记显示。不需要上游配置—— 代理会根据线路格式,将 Anthropic 格式的调用路由到 Anthropic。
AWS Bedrock(直接捕获)
- 通过标准凭证链为 ledger 提供独立的 AWS 凭证
(环境变量、
~/.aws配置文件或实例角色),并限定为bedrock:InvokeModel和bedrock:InvokeModelWithResponseStream, 然后安装额外依赖并重启:pip install "agentic-ledger[bedrock]" agenticledger stop && agenticledger start - 检查 ⚙ Settings 面板:Bedrock 行应显示“正在以 ledger 的身份在 中签名”。
- 将客户端指向代理——Claude Code:
boto3:export CLAUDE_CODE_USE_BEDROCK=1 export ANTHROPIC_BEDROCK_BASE_URL=http://localhost:8000boto3.client("bedrock-runtime", endpoint_url="http://localhost:8000")。 - 发起一次调用;它会带有橙色 B 标记显示。ledger 会移除调用方的 身份,并使用自身凭证重新签名。完整指南: docs/integrations/bedrock.md。
通过公司网关使用 AWS Bedrock
许多公司会通过网关接入 Bedrock,并由网关自行处理身份验证;此时 Claude Code 的配置会包含 CLAUDE_CODE_SKIP_BEDROCK_AUTH=1,并将 ANTHROPIC_BEDROCK_BASE_URL 指向网关,通常这些设置来自受管理的设置文件。ledger 位于该网关前面,会按 Agent 发送的内容原样转发每次调用,包括标头:无需签名,你这边也无需提供 AWS 凭证。
- 告诉 ledger 网关的位置(即之前
ANTHROPIC_BEDROCK_BASE_URL指向的主机):agenticledger config set proxy.bedrock_gateway_url https://bedrock-gateway.company.example agenticledger stop && agenticledger start - 改为将 Claude Code 指向 ledger:
ANTHROPIC_BEDROCK_BASE_URL=http://localhost:8000。如果该值位于 IT 管理的设置文件(/Library/Application Support/ClaudeCode/managed-settings.json)中,它会覆盖所有其他设置,因此必须由 IT 修改;如果它位于~/.claude/settings.json中,则在该文件中编辑。 /health和 ⚙ Settings 面板会显示“正在按发送给 ... 网关的内容转发”。调用会带有 Bedrock 标记和带区域前缀的模型 ID 显示。
Azure OpenAI
- 将上游设为你的资源:
agenticledger config set proxy.upstream_url https://<resource>.openai.azure.com agenticledger stop && agenticledger start - 将客户端的 Azure 端点指向
http://localhost:8000;保留原有的api-key请求头。 - 调用会标记为
azure-openai,并根据响应中注明的模型计价,因此部署别名无法掩盖实际模型。完整指南: docs/integrations/azure-openai.md。
本地模型(LM Studio、搭配 OpenAI API 使用的 Ollama)
- 将上游设为本地服务:
agenticledger config set proxy.upstream_url http://localhost:1234 agenticledger stop && agenticledger start - 在 Agent 中执行
export OPENAI_BASE_URL=http://localhost:8000/v1。 - 调用会显示紫色标记,费用为 $0。完整指南: docs/integrations/lm-studio.md。
网关(OpenRouter、LiteLLM)
- 将上游设为网关:
agenticledger config set proxy.upstream_url https://openrouter.ai/api agenticledger stop && agenticledger start - 执行
export OPENAI_BASE_URL=http://localhost:8000/v1;保留原有的网关 密钥。 - 通过子字符串匹配,带网关前缀的模型 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 | 使用的模型 |
provider | openai 或 anthropic |
messages | 发送给模型的完整消息历史 |
system_prompt | 提取的系统提示词 |
tools | 模型可用的工具定义 |
tool_calls | 模型决定调用的工具 |
tool_results | 工具返回的内容(来自下一次调用的消息) |
content | 模型的文本输出 |
stop_reason | 模型停止的原因 |
tokens_in / tokens_out | Token 用量 |
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_to | Flow DAG 的 Agent 交接跟踪 |
除了模型调用之外,会话还可以记录 Agent 自身的活动:agenticledger connect claude-code --hooks 会安装 Claude Code hooks,将 Agent 在其机器上的操作(运行的工具及其输入、输出和持续时间,请求或拒绝的权限、子 Agent、上下文压缩、会话开始和结束)发送到 /v1/hooks/claude-code。这些记录会显示在会话的 Activity 选项卡中,可在托管网关后使用,且绝不会用于引导 Agent。
API 参考
| Method | Endpoint | Description |
|---|---|---|
GET | /health | 存活状态 - {"status":"ok","version":"..."}。无需认证,绝不访问存储。 |
GET | /readyz | 就绪状态 - 对存储执行 ping;无法连接时返回 503。同时报告 capture_dropped。 |
GET | /metrics | Prometheus 指标(已持久化/丢弃的捕获数量、队列深度)。 |
GET | /api/audit | 敏感操作的审计记录,按时间从新到旧排列,采用哈希链;可按 action、actor、target、since、until 筛选,并使用 before_seq 分页(管理员)。 |
GET | /api/audit/verify | 遍历审计哈希链,并指出第一个断点(如有)(管理员)。 |
DELETE | /api/users/{user_id} | 删除权:删除某用户的所有已捕获调用(管理员)。 |
GET | / | 实时仪表板 |
WS | /ws | WebSocket 流 - 为实时仪表板更新提供支持 |
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 | /mcp | MCP 工具服务 - list_sessions、explain、get_session、search、list_runs、get_run_status |
POST | /v1/traces | OTLP/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 | 否 | 8443 | https 仪表板监听器的端口。 |
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) / 提供商 API | Claude 模型的跨提供商重放目标。 |
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 | 否 | full | full 会存储所有内容;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_STATUS | 429 | 预算限制触发时的 HTTP 状态码。429 会附带准确的 Retry-After(距 UTC 午夜窗口重置的秒数);如果客户端会激进地重试 429,可设为 402——不会有请求重试 Payment Required。 |
AGENTICLEDGER_BUDGET_ACTION | block | 超出预算时的处理方式:block 返回 HTTP 429(调用不会到达大模型),warn 允许调用通过并触发 webhook 警报,both 则阻止调用并触发 webhook。 |
AGENTICLEDGER_BUDGET_UNPRICED | allow | 无法统计价格包中未定价模型的费用。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_ACTION | warn | warn 会记录 loop_flags 并触发 loop_flag webhook 警报;block 还会对触发防护规则的会话返回 HTTP 429(loop_detected),记录每次拒绝,并可在仪表板中从会话页面解除限制,无需重启(DELETE /api/sessions/{id}/loop-block;防护规则会从解除限制的位置重新启用);off 会禁用推断。 |
AGENTICLEDGER_LOOP_REPEAT_THRESHOLD | 3 | 在将线程标记为卡住之前,允许连续出现的相同工具调用次数(工具和参数均相同)。 |
AGENTICLEDGER_LOOP_MAX_STEPS | (none) | 将超过此 ReAct 步数的线程标记为异常(在 block 模式下会停止线程)。 |
AGENTICLEDGER_LOOP_RUN_GAP_SECONDS | 900 | 新上下文派生之间的最大间隔(系统提示词相同),在此间隔内仍计为同一次运行的迭代。 |
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_FORMAT | auto | 负载格式: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_NAME | agenticledger | 向收集器报告的 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 |
editor | viewer 的权限 + 删除会话 |
admin | editor 的权限 + 管理 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-environment | development | production、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_NAME | agenticledger | 发出的资源中 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_to | Agent 交接 |
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
该流水线会运行三个任务:
- Docker - 为 linux/amd64 + linux/arm64 构建
ghcr.io/shekharbhardwaj/agentic-ledger:{version}和:latest,推送时附带 SBOM + provenance 证明,使用 Sigstore cosign(无密钥)对摘要签名,并在配置了DOCKERHUB_USERNAME/DOCKERHUB_TOKEN密钥时镜像到 Docker Hub - PyPI - 使用可信发布(无需 API 令牌)构建并向 PyPI 发布
agentic-ledger=={version},附带 PEP 740 证明 - GitHub Release - 创建包含自动生成的变更日志的发布,并附上镜像 SBOM(SPDX)
首次设置 PyPI(仅需一次):
- 前往 pypi.org/manage/account/publishing
- 添加一个新的待处理发布者:
PyPI project name: agentic-ledger Owner: ShekharBhardwaj Repository: AgenticLedger Workflow name: release.yml Environment name: pypi - 在 GitHub 中创建
pypi环境:repo → Settings → Environments → New environment → 将其命名为pypi - 就这样——无需配置密钥
故障排除
从这里开始: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
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。