
上个月参与维护的一个开源项目,一周之内涌进来 40 个 issue。手工分类花了四个小时:读内容、打标签、定优先级、回复。动念头想上个 Agent 帮我做第一轮筛选。问题是:项目没钱买云资源,没 GPU,也没有任何 AI 预算。
零预算不是口号,是硬约束。
这个仓库收到的 issue 包括 bug 报告、功能需求、环境配置问题各种混在一起。大部分 issue 篇幅不长,但有些会带上一堆堆堆栈日志。工作量波动很大:有时候好几天没动静,有时候一觉醒来堆了 10 个。
常规思路是上托管式 Agent 平台。常规思路也是要花钱的。我给自己定了个不同的约束:MonkeyCode 的免费模型访问加上免费服务器。提前说明:这篇东西是 MonkeyCode 产品推广的一部分。MonkeyCode 是个开源项目,写稿时宣传的是一千万 Token 免费额度加免费服务器。具体限制会变,用之前去项目文档里核实一下。
仓库细节只是具体案例。可复用的是那套 harness 和记账方法。
动手写 Agent 代码之前,我先定了三条成功标准:
第四条隐含标准才是真正重要的:搞清楚每一个 Token 花哪儿去了。
这个 Agent 有三个工具加一道护栏:
list_issues — 拉取 open 状态的 issue,每次一页。get_issue — 拉取单个 issue 的完整内容。classify — 返回标签、置信度分数和草稿回复。每次工具调用都在 Agent 继续之前记录日志。这个日志记录机制才是本文真正要说的东西。
核心 harness 来了。每次工具调用记录一行 JSON(JSONL)格式的数据:
# tool_budget_ledger.py
import json
from dataclasses import dataclass, asdict @dataclass
class ToolCall: ts: float agent_step: int tool: str input_tokens: int output_tokens: int status: str # ok | error | skipped
latency_ms: int def append_call(run_id: str, call: ToolCall) -> None: path = f"ledgers/{run_id}.jsonl" with open(path, "a", encoding="utf-8") as f: f.write(json.dumps(asdict(call)) + "\n")
统计器把账本转成按工具分项的成本表:
def summarize(run_id: str) -> dict: totals = {} with open(f"ledgers/{run_id}.jsonl", encoding="utf-8") as f: for line in f: c = json.loads(line) t = totals.setdefault( c["tool"], {"calls": 0, "input": 0, "output": 0, "errors": 0}, ) t["calls"] += 1 t["input"] += c["input_tokens"] t["output"] += c["output_tokens"] t["errors"] += int(c["status"] == "error") return totals
预算护栏放在循环里,不放在钱包里:
BUDGET = 10_000_000 # free-tier allowance, operator-reported; verify in docs
RESERVE = 0.8 # stop at 80% to leave headroom
def within_budget(spent: int) -> bool: return spent < BUDGET * RESERVE
故意设得保守一点。跑到 80% 就停虽然有点烦,但跑到 100% 半途停下导致 20 个 issue 没分类、还没额度补救,那才是真麻烦。
用合成数据跑了个 10 个 issue 的试点来验证 harness,数据准确之后才动真格额度。下面的数字是示意性的,记账逻辑跟 harness 记录任何 provider 的方式完全一致。
| 工具 | 调用次数 | 输入 Token | 输出 Token | 占比 |
|---|---|---|---|---|
list_issues |
6 | 4,200 | 900 | 6% |
get_issue |
10 | 61,400 | 1,800 | 74% |
classify |
10 | 9,800 | 2,100 | 14% |
post_comment |
4 | 3,100 | 800 | 6% |
结论非常明显。get_issue 吃掉了 74% 的预算,根本原因是工具调用 Agent 的一个天然特性:工具返回结果会在后续每一步重新发给模型。一个两千 Token 的 issue 主体,模型第一次看到花两千,第二次看到又花两千,第三次还是两千。
这张表催生了三个改进:
get_issue 和 classify 合并成一步,主体只发一次。改完试点跑下来,每个 issue 的成本降了大概一半,估算的周消耗稳稳落在额度范围内。
这套路子不是万能的。下面是我用来判断免费层分诊 Agent 适不适用的表格:
| 工作负载 | 免费层适用性 | 原因 |
|---|---|---|
| 每周少于 200 个 issue,主体小于 1k Token | 适用 | 额度够用,还有余量 |
| 夜间批量分诊 | 适用 | 定时任务友好,不介意延迟 |
| 长文档审核(50k Token 文件) | 不适用 | 一个文件就能把额度吃掉大半 |
| 2 秒内实时响应 | 不适用 | 免费服务器冷启动跟 SLA 合不来 |
| 合规敏感数据 | 不适用 | 送出去之前先核实数据处理方式 |
对延迟有 SLA 要求、合规限制严格、或者文档量大的工作负载,不应该在免费服务器加 Token 额度上建生产系统。那种场景下 harness 还是有用的,但用途是作为测量工具,不是生产平台。先测量,再决定该为什么付钱。
harness 大概 120 行代码,一个文件搞定。想搞清楚自己的 Agent Token 到底花哪儿去了,先把账本搭起来,别急着换更大的模型。MonkeyCode 免费层是个跑这个实验的合理起点,项目文档里有最新的限制说明。跑试点、读表格,让数字说话。