面向 AI Agent 消息的无损编解码器:Token 减少 36%,并计入解码开销
英文标题:🔶 Lossless codec for AI agent messages – 36% fewer tokens, overhead counted
开源项目 `a2acompress` 提供了一种用于 Agent 间交接消息的紧凑无损线格式,并在保留集 ToolBench 轨迹上将完整 Token 成本从 140,661 降至 89,235,节省 36.6%。该结果将紧凑载荷、模型理解格式所需的重建指令,以及随会话传输的学习型字典全部计入成本,而非只比较压缩后的载荷大小。项目采用逐字节可逆验证、按完整轨迹划分训练与测试集,并使用真实 `cl100k_base` 编码器统计 Token。对于能同时控制消息编码端和解码端的多 Agent 系统,它可降低工具目录、重复输出和结构化消息带来的上下文开销;但不适合作为任意 Prompt 的即插即用压缩代理。
33.2 KB
44.5 KB
54.3 KB
中文
一种用于 Agent 到 Agent 交接的紧凑无损线格式——在留出的 ToolBench 轨迹上,可减少 36% 的真实 cl100k_base Token,并将每一字节的开销都计入其中。
多 Agent 流水线(规划器 → 构建器 → 审核器、工具循环,以及 LangGraph / CrewAI / AutoGen 风格的编排)会将大部分上下文窗口消耗在重复发送结构信息上:JSON 键、引号、重复陈述的标识符、工具目录,以及两次交接后仍被原样引用的输出。如果你能控制交接的两端,这些结构可以被自由压缩——前提是压缩能够精确可逆,并且你如实计算解码所需的成本。
a2acompress 就是这样的编解码器,同时还提供用于确保结果可信的基准测试框架。
原始规范 JSON ████████████████████████████████████ 140,661 tokens
a2c/1 完整成本 ███████████████████████ 89,235 tokens −36.6%
└── 载荷 79,439 + 解码指令 9,796 + 字典 0
在留出的 196 条真实 ToolBench 轨迹(3,013 次交接)上测试,使用实际 cl100k_base Token 计数;每条记录均实现逐字节精确往返。可通过下方一条命令复现。
这个数字为何可信
多数压缩演示只比较载荷字节数,却忽略接收方需要被告知如何读取载荷的成本。在这里,完整成本是唯一的核心指标:
完整成本 = 紧凑载荷
+ 模型解码所需的重建指令
+ 一并传输的任何学习型字典
测试套件和 CI 还强制执行以下三项规则:
-
逐字节精确,否则淘汰。 每一种配置都必须将每条留出记录解码回完全相同的规范 JSON,否则不能获胜。
-
按完整轨迹划分训练/测试集。 任何学习得到的内容(字典、调优选择)只能接触训练任务;报告中的数字来自优化器从未接触过的任务,并使用另外三个划分种子再次验证。
-
不虚构 Token。 GPT 和 Claude API 无法消费自定义 Token ID。这里的一切都是使用真实
cl100k_base编码器统计的普通文本。传输尺寸(gzip)会单独报告,绝不会被包装成 Token 节省。pip install -e . a2acompress optimize --adapter synthetic --limit 40 --output release
该命令会在合成语料上运行完整的有界优化循环,并写入一个发布目录,其中包含报告、结果 JSON、选定协议、图表,以及 practical / research-only 判定。
在公开 ToolBench 轨迹上运行真实基准测试:
a2acompress fetch --dataset toolbench --limit 240 --output data/toolbench
a2acompress optimize --adapter toolbench --source data/toolbench --seed 7 --output release
或者直接使用编解码器:
from a2acompress.protocol import ProtocolOptions, encode_session, decode_session
options = ProtocolOptions(
positional_body=True, packed_header=True,
minimal_instructions=True, inline_backrefs=True, token_aligned_refs=True,
)
encoded = encode_session(records, options) # 输入一条任务轨迹
restored = decode_session(encoded.payload, options)
assert restored == records # 必须始终成立,否则就是 bug
CLI:fetch · normalize · train · encode · decode · verify · benchmark · optimize。
每次交接(计划、消息、工具调用/结果、状态、工件、审查、错误、最终结果)都会先被规范化为一种统一的记录形状。随后,每条记录编码为一行:
#task|agents
c13|tool_catalog|image_search;{"count":5,"q":"web design"};c1
r31||c1;The search returned 5 results: ${2f:8a} …
f10||done — ${0:2q:1d4}
节省由以下机制叠加而成,且全部可逆:
| 机制 | 作用 |
|---|---|
| 紧凑模式 | 单字符键、省略默认值、位置字段、打包头部 |
| 值引用 | $3 重复此前出现的值;首次出现即为定义 |
| 内联反向引用 | ${o:l} 从会话先前内容中拼接一段字符范围——类似 LZ,但载荷仍是可读文本,且无需传输字典 |
| Token 对齐拼接 | 当_测得的_ Token 成本更优时,引用边界会偏移若干字符;无法优于自身字面量的引用会被丢弃 |
| 自适应指令 | 解码指令按会话传输、经过压缩,并且只描述该会话实际使用的特性 |
内联反向引用是核心机制:最终回答会原样引用工具输出,工具目录会针对每个工具重复其自身的封装结构——一个 6 Token 的标记可以替代任意长度的片段,解码器通过重放会话重建全部内容。在 ToolBench 上,它完全取代了学习型字典(优化器保留了 0 个条目:按会话传输字典的成本高于其节省的成本——这是测得的结果,而非假设)。
格式中的每个常量——分隔符字符、标记语法、片段阈值——均通过衡量真实 cl100k_base 成本选出,而不是凭猜测决定。那些未胜出的替代方案(制表符分隔、较长 n-gram、惰性字典引导)及其数据都记录在发布报告中。
a2acompress optimize 是一次有界搜索,而不是演示脚本:
- 在一组配置网格中评估基线协议。
- 验证每种配置的无损性;失败的配置不能获胜。
- 每个周期只启用一项改进,并根据训练数据上的探测结果选择。
- 在连续两个无改进周期或达到 10 个周期后停止;选择成本最低且已验证的获胜方案。
- 在另外三个划分种子上重新测试获胜方案,并报告结果范围。
- 写入带有清单的发布目录(种子、语料指纹、搜索空间),使任何结果都可逐比特复现。
判定阈值:practical 要求完整成本节省 ≥15%,且在 10 次交接内达到盈亏平衡。当前获胜方案节省 36.6%,并在中位数会话的第一次交接时即达到盈亏平衡。
何时使用,以及何时不该使用
适用场景: 你运行一个多 Agent 系统,由同一进程(或你控制的两个进程)对交接消息进行编码和解码;你按 Token 付费;并且交接消息包含重复结构——如工具目录、引用的输出和符合模式的消息。
不适用场景:
- 你希望获得一个能压缩任意 Prompt 的即插即用代理。这是一种协议;两端都必须能使用它。
- 接收模型必须直接对紧凑格式采取行动,且在任何风险等级下都不能出现解码错误。模型根据随附指令读取该格式;这种路径如实计入了 Token 成本,但本质上仍是模型在阅读一份规范——在信任它处理生产流量前,请先在自己的流量上测试。
- 你的消息大多是独特的散文文本。这里压缩后仍保留的约 63% 内容就是独特内容;缺少结构性重复的语料,节省幅度会更小。
相关工作: TOON 通过一次声明形状来压缩用于 Prompt 的表格 JSON(在统一数组上约为 40%);LLMLingua 风格的 Prompt 压缩则是有损的。a2acompress 的不同之处在于:它面向异构 Agent 轨迹实现无损压缩,增加会话重放引用和 LZ 风格拼接,并将每一字节的解码开销都计入自身成本。
| 留出集指标(种子 7) | 数值 |
|---|---|
| 原始规范 JSON | 140,661 tokens |
| 紧凑载荷 | 79,439 |
| 重建指令 | 9,796 |
| 学习型字典 | 0 |
| 完整成本 | 89,235(−36.6%) |
| 仅载荷(非核心主张) | −43.5% |
| 中位数盈亏平衡点 | 1 次交接 |
| 从未达到盈亏平衡的会话 | 39 个中为 0 个 |
| 种子 11/23/47 上的稳定性 | −36.1% / −36.0% / −35.2% |
| 往返结果 | 每条记录均逐字节精确 |
完整细节见:release/optimization_report.md,每个已评估配置见 release/optimization_results.json。
目前仅在一个公开语料库(ToolBench)上完成基准测试。jsonl 适配器可接收你自己的轨迹——只需包含 role/content 的 JSONL——优化循环将给出_你的_结果:
a2acompress optimize --adapter jsonl --source your_traces.jsonl --output my_release
如果你在自己的语料上运行它,无论结果好坏,在 issue 中分享你的数据都是最有价值的贡献。
pip install -e ".[dev]"
python -m pytest tests -q
CI 会运行单元测试、针对对抗性输入的无损往返测试夹具、合成基准测试、完整优化循环,以及发布检查器;如果报告的算术、判定或稳定性复测无法成立,构建就会失败。
一个 TypeScript 版本的编解码器(与 Python 实现保持字节级一致,并通过交叉测试验证)为浏览器实验室提供支持,可实时编码、解码并验证往返结果;它位于配套项目中,将单独发布。
MIT——见 LICENSE。
English / 原文
A compact, lossless wire format for agent-to-agent handoffs — cuts 36% of realcl100k_base tokens on held-out ToolBench trajectories, with every byte of overhead counted against it.
Multi-agent pipelines (planner → builder → reviewer, tool loops, LangGraph / CrewAI / AutoGen-style orchestration) burn most of their context window re-sending structure: JSON keys, quoting, restated identifiers, tool catalogs, and outputs quoted verbatim two handoffs later. If you control both sides of a handoff, that structure is free to compress — as long as the compression is exactly reversible and you are honest about what decoding costs.
a2acompress is that codec, plus the benchmark harness that keeps it honest.
raw canonical JSON ████████████████████████████████████ 140,661 tokens
a2c/1 full cost ███████████████████████ 89,235 tokens −36.6%
└── payload 79,439 + decode instructions 9,796 + dictionary 0
Held-out split of 196 real ToolBench trajectories (3,013 handoffs), actualcl100k_base token counts, byte-exact round trip on every record. Reproduce with one command below.
What makes the number honest
Most compression demos compare payload bytes and skip the part where the receiver needs to be told how to read the payload. Here, full cost is the only headline number:
full cost = compact payload
+ the reconstruction instructions a model needs to decode it
+ any learned dictionary shipped alongside
Three more rules, enforced by the test suite and CI:
- Byte-exact or rejected. Every configuration must decode back to identical canonical JSON for every held-out record, or it cannot win.
- Train/test split by complete trajectory. Anything learned (dictionaries, tuning choices) sees training tasks only; the reported number comes from tasks the optimizer never touched, re-verified across three more split seeds.
- No invented tokens. GPT and Claude APIs cannot consume custom token IDs. Everything here is ordinary text counted with the real
cl100k_baseencoder. Transport size (gzip) is reported separately and never sold as token savings.
pip install -e .
a2acompress optimize --adapter synthetic --limit 40 --output release
That runs the full bounded optimize loop on a synthetic corpus and writes a release folder: report, results JSON, the selected protocol, charts, and a practical / research-only verdict.
The real benchmark on public ToolBench trajectories:
a2acompress fetch --dataset toolbench --limit 240 --output data/toolbench
a2acompress optimize --adapter toolbench --source data/toolbench --seed 7 --output release
Or use the codec directly:
from a2acompress.protocol import ProtocolOptions, encode_session, decode_session
options = ProtocolOptions(
positional_body=True, packed_header=True,
minimal_instructions=True, inline_backrefs=True, token_aligned_refs=True,
)
encoded = encode_session(records, options) # one task trajectory in
restored = decode_session(encoded.payload, options)
assert restored == records # always, or it's a bug
CLI: fetch · normalize · train · encode · decode · verify · benchmark · optimize.
Every handoff (plan, message, tool call/result, status, artifact, review, error, final) is first normalized to one canonical record shape. Records then encode to one line each:
#task|agents
c13|tool_catalog|image_search;{"count":5,"q":"web design"};c1
r31||c1;The search returned 5 results: ${2f:8a} …
f10||done — ${0:2q:1d4}
The savings stack, all reversible:
| Mechanism | What it does |
|---|---|
| compact schema | one-char keys, defaults omitted, positional fields, packed headers |
| value references | $3 repeats an earlier value; the first occurrence is the definition |
| inline backreferences | ${o:l} splices a character span from earlier in the session — LZ-style, but the payload stays readable text and no dictionary ships |
| token-aligned splices | ref boundaries shift a few chars when the measured token cost improves; refs that don't beat their own literal are dropped |
| adaptive instructions | the decode instructions ship per session, compressed, and only describe features that session actually uses |
The inline backreference is the workhorse: final answers quote tool outputs verbatim, tool catalogs repeat their own envelope per tool — one 6-token marker replaces spans of any length, and the decoder rebuilds everything by replaying the session. On ToolBench it fully displaced the learned dictionary (the optimizer kept 0 entries: shipping a dictionary per session costs more than it saves — measured, not assumed).
Every constant in the format — separator characters, marker syntax, span thresholds — was chosen by measuring real cl100k_base costs, not guessed. The alternatives that lost (tab separators, longer n-grams, lazy dictionary bootstrap) are documented in the release report with their numbers.
a2acompress optimize is a bounded search, not a demo script:
- evaluate the baseline protocol across a grid of configurations
- verify losslessness for every configuration; failures cannot win
- enable one improvement per cycle, chosen by a probe on training data
- stop after two stale cycles or 10 cycles; select the cheapest verified winner
- re-test the winner on three other split seeds and report the spread
- write a release folder with a manifest (seed, corpus fingerprint, search space) so any result is reproducible bit-for-bit
Verdict thresholds: practical needs ≥15% full-cost saving and break-even within 10 handoffs. The current winner saves 36.6% and breaks even on the first handoff of the median session.
When to use it — and when not to
Good fit: you run a multi-agent system where the same process (or two processes you control) encodes and decodes handoffs, you pay per token, and your handoffs carry repeated structure — tool catalogs, quoted outputs, schema-shaped messages.
Not a fit:
- You want a drop-in proxy that shrinks arbitrary prompts. This is a protocol; both sides must speak it.
- Your receiving model must act on the compact form directly with zero decode errors at any stakes. A model reads the format from the shipped instructions; that path is honest about its token cost but is still a model reading a spec — test on your own traffic before trusting it.
- Your messages are mostly unique prose. The ~63% that survives compression here is the unique content; a corpus without structural repetition will save less.
Related work: TOON shrinks tabular JSON for prompts by declaring shape once (~40% on uniform arrays); LLMLingua-style prompt compression is lossy. a2acompress differs by being lossless on heterogeneous agent trajectories, adding session-replay references and LZ-style splices, and charging itself for every byte of decode overhead.
| Held-out metric (seed 7) | Value |
|---|---|
| Raw canonical JSON | 140,661 tokens |
| Compact payload | 79,439 |
| Reconstruction instructions | 9,796 |
| Learned dictionary | 0 |
| Full cost | 89,235 (−36.6%) |
| Payload-only (not the claim) | −43.5% |
| Median break-even | 1 handoff |
| Sessions never breaking even | 0 of 39 |
| Stability on seeds 11/23/47 | −36.1% / −36.0% / −35.2% |
| Round trip | byte-exact, every record |
Full detail: release/optimization_report.md, every evaluated configuration in release/optimization_results.json.
Benchmarked on one public corpus (ToolBench) so far. The jsonl adapter takes your own traces — a role/content JSONL is enough — and the loop will tell you your number:
a2acompress optimize --adapter jsonl --source your_traces.jsonl --output my_release
If you run it on your own corpus, an issue with your numbers (good or bad) is the most useful contribution you can make.
pip install -e ".[dev]"
python -m pytest tests -q
CI runs the unit tests, lossless round-trip fixtures against adversarial inputs, a synthetic benchmark, the full optimize loop, and a release checker that fails the build if a report's arithmetic, verdict, or stability re-tests don't hold up.
A TypeScript port of the codec (byte-parity with Python, verified by cross-tests) powers a browser lab that encodes, decodes, and verifies the round trip live; it lives in a companion project and will be published separately.
MIT — see LICENSE.

