作者为AI编程工具构建了专门的用量追踪方案,发现现有方案(ccusage、token-tracker等)要么追求全覆盖要么偏向视觉探索,但都缺乏对「任务归属是否可信」的边界判断能力。关键洞见是会话级测量和任务归属是两个不同的断言,不应混淆。
当你真正用 Claude Code 或 Codex 做过工作,一个简单的总量数字就不够用了。你想知道是哪次改动消耗了它。
我构建 agent-cost,并不是因为之前没有现成的 token 和成本追踪工具。我知道有多 agent 汇报 CLI、本地仪表盘、OpenTelemetry 风格的观测栈。我甚至在 Notion 里搭过类似的视图。
问题出现在我把这类汇报引入运营流程时。我需要 agent 日志留在本地。我希望运行时依赖面小、可审计的自定义指标、以及能被其他工具消费的结构化结果。最重要的是,我需要让「会话级测量」和「任务归属」保持为两个不同的断言。
我不需要又一个万能仪表盘。我需要的是一个在仪表盘之下的边界层,能够回答:这个数字有足够的支撑证据,可以进入任务核算吗?
不同工具针对不同场景做了优化。像 ccusage 这样覆盖面广的 CLI,在需要跨 agent 统计时很有用。token-tracker 或 AgentMeter 这类本地界面更适合对项目、会话、子 agent 和工具进行可视化探索。OpenTelemetry 栈是舰队级指标、日志和链路追踪的自然选择。
这些并非 agent-cost 的低级版本。它们服务的是不同的用例和信任模型。
我想要的这一层是这样的:
本地观测
-> 可审计的标准化事实
-> 明确的定价状态
-> 调用方选择的会话
-> 任务归属策略
-> 可选仪表盘 / Notion / 规格通道
agent-cost 读取 Claude Code 和 Codex CLI 已经写在本地磁盘的日志。它把每个使用事件标准化为一条事实,包含模型、token 类型、时间戳和数量。运行时它不发起网络请求,也不声明任何 Python 运行时依赖。它的价格目录有版本号和 SHA-256 摘要,两者都会携带到机器可读的输出中。
这个「零网络」的声明是有意局限在运行时行为。从 PyPI 安装仍然意味着信任注册表、安装器、构建后端、Python 运行时和操作系统。工具也需要访问源日志。设计收窄了运行时数据泄露和依赖面,但不能让供应链消失。
在构建任务级成本报告时,有一条诱人的捷径:
在某个时间窗口内计量使用量。
找到该窗口内活跃的 issue 或分支。
按工时或 commit 数量分摊总量。
这样总能得出加起来对的数字。但一致性来自分摊规则,而非观测。
一个会话可以覆盖多个任务。一个任务可以横跨多个会话。一个分支可以在操作者调查另一个问题或 review 别人代码时保持不变。流逝的时间并不描述 prompt 和工具调用的计算权重。
我想要的恒定不变式是:
会话使用量是可观测的。会话到任务的归属是另一条独立的断言。
agent-cost measure 只接受调用方选定的会话 ID:
agent-cost measure \
--session-id <session-a> \
--session-id <session-b> \
--format json
它不通过分支、PR 或时间戳来推断任务。已有任务到会话绑定的上游流程会传入对应的会话集合。
例如,spec-lane 适配器将 agent-cost 作为子进程调用,然后检查 JSON、measure/v1 协议版本、schema 以及禁止的个人维度。agent-cost 不会获知任务是什么。知道任务的调用方才选择会话。
如果一个会话跨越了多个任务,且没有办法合理地拆分,我宁可让那部分使用量不归属,也不愿制造一个看起来精确的分摊数字。未知代表有待补充的证据,而不是零。
agent-cost 携带不确定性,而不是把它平滑掉。
未知模型不予定价。Claude cache write 没有 TTL 细分的话,按较便宜的五分钟费率计价,并标注为 lower_bound。Codex 日志不暴露 cache-write token,所以工具不会虚构一行零值的 cache-write。格式错误的事件、无法读取的文件、递减的累计计数器都会保留在 data_quality 中可见。
「Fail closed」不是说每个不完美的输入都会导致命令崩溃。它是说不支持的定价或归属不会悄悄变成下游的确认值。
2026 年 8 月 23 日,我在临时 uvx 目录下重新运行了已发布的 coding-agent-cost 0.1.0 包。它的 doctor 命令找到了本地源,加载了目录版本 2026-07-29。未知的模型路径仍然会拒绝一个虚构的模型:
$ uvx --refresh --from coding-agent-cost \
agent-cost rates show --model model-not-in-catalog
[unpriced] no rate entry for 'model-not-in-catalog'
未知行旁边的数字零并不是在说该使用量是免费的。消费者必须检查 pricing_status 和 unpriced_tokens,然后选择策略:从不标题中排除该值、停止工作流,或提供一个已验证的目录。
输出字段是 estimated_cost_usd,不是账单。本地日志无法完全恢复津贴、合同、积分和批量使用的差异。这个数字是附属于观测到 token 的列表价估计。
这里有刻意的局限。agent-cost 本身不会把一个会话标注为属于某个 issue。本地执行不能消除安装时的供应链风险,也不能免除对本地日志访问的信任需求。
作为交换,每一层都有更窄的断言:
本地日志支撑会话使用量事实。
带版本的目录支撑估计价格。
不支持的价格保持 unpriced 或 lower_bound。
调用方拥有任务绑定作为独立证据。
模糊的使用量不会仅仅为了凑满总量而被静默分摊。
这不是反对仪表盘的论点。当可视化探索是工作时,用仪表盘。当舰队级可观测性是工作时,用 OpenTelemetry。当需要一个子进程契约且希望测量与归属策略保持分离时,用一个小的核算原语。
保持未知可见不是测量失败。它是让上一层避免虚假信心的方式。
从 agent-cost 中 60 秒快速上手开始。如果你同时需要一个工作流来拥有任务归属,见 spec-lane。