Tokenless Runtime 库

September 9, 2026 · View on GitHub

English

目标

anolisa-tokenless 是框架无关的进程内 Tokenless SDK。平台 Wheel 同时包含 PyO3 Runtime 和固定版本的 RTK 可执行文件,因此 Python 应用不要求 tokenlessrtk 出现在 PATH 中。

公开的 TokenlessSdk 把宿主框架的四个生命周期映射为 Tokenless 行为:

生命周期行为
before_model可恢复的 Function Calling Schema 压缩,并按需发布恢复工具
pre_tool对 Adapter 明确指定的命令字段执行 RTK 改写
post_tool状态路由、响应压缩、TOON 候选选择和环境错误提示
retrieve受可见 marker 授权的 byte-exact Stash 恢复

Tool Ready 在产品范围内硬关闭,不属于该 API。

协议与状态

Adapter 把框架对象转换为四组不可变 Request/Response:BeforeModelRequestPreToolRequestPostToolRequestRetrieveRequestAttribution 要求 Agent 和 Session 标识;PreTool 与普通 PostTool 还必须提供 Tool Use 标识。工具 Schema 统一为 OpenAI Function Calling JSON,但生命周期操作是 Tokenless 自身契约,不是 OpenAI 请求。

tokenless-runtime 统一持有 SQLite Stash 和统计记录器。Schema 与响应压缩共享 Stash, 候选被丢弃时会回滚对应 key。TOON 作为 Rust 库直接链接,不启动进程。只有 Adapter 提供 command_field 时才调用 RTK;每个改写后的 wrapper 都锚定到 Wheel 内置文件,并 携带本次执行的归属信息。内容检测、阈值、TOON 选择、诊断、授权和 Stash 策略都保留在 Rust Core,而不是 Python 配置中。

SDK 不保存进程级“当前 Session”。before_model 返回精确的可见 Marker 集合。Adapter 声明自己是否已有 Marker 授权恢复路径,并持有面向 Agent 的命令或 Tool 声明。AgentScope 在模型调用之间保持 Retrieve Tool 静态,把 Marker 集合保存在框架 Session 状态中;retrieve 只授权该集合 中的 Marker。宿主应用继续保存原始工具结果供 UI 和业务逻辑使用,只把复制 后的最终模型可见文本传给 post_tool;Retrieve 输出禁止再次进入 PostTool。

非法输入、内置 RTK 缺失、生命周期操作失败、挂载失败和工具重名会快速失败。Passthrough、 No Savings 和 Recoverability Unavailable 等正常 Core Disposition 返回 typed 结果。候选 只有严格更短时才会采用;Schema 和响应截断还必须能够恢复。

搜索路径共享

PostTool 仅在搜索路径共享已开启、来源为 api_response 且支持文本替换时,将识别为 search_results 的内容交给 SearchResultsCompressor。这是按内容派发的 Core 能力,不限定 Agent ID; 文件内容和命令输出均不进入该域,包括未由 RTK 处理的 Bash 输出。 成功的 path:line:text 列表至少包含三条记录,连续记录可以共享完整文件路径。 行号、正文、顺序和换行保持字节可逆。输入契约不包含路径内的冒号和上下文列表; 任意不支持的记录都会拒绝整份候选。字节数与估算 Token 均减少后,再经过现有 Runtime 仲裁。 实际采用时操作为 search_path_sharing,Python SDK 对应 AppliedOperation.SEARCH_PATH_SHARING; 恢复等级为 lossless,不写入 Stash。

Claude Code Adapter 仅提取无上下文选项的原生 Grep mode=content 响应,将其文本槽声明为 API 响应,再只替换原输出对象的 content 字段。包括宿主限额在内的其他元数据保持不变; 完整性指保留收到的所有记录,不表示宿主裁剪前的全部可能命中。 其他 Grep 模式和宿主保留既有路由。RTK 负责的 Bash 输出继续绕过原生 PostTool 压缩。

搜索路径共享默认开启。CLI 可通过 TOKENLESS_SEARCH_PATH_SHARING_ENABLED=0 关闭; 未设置时保持开启,1trueyes(不区分大小写)也表示开启;空值和其他值均关闭。 该变量独立于 JSON 配置文件。 Rust 使用 RuntimeConfig.search_path_sharing_enabled;Python 使用 TokenlessConfig(search_path_sharing_enabled=False)TokenlessRuntime 的同名参数。 关闭该域时搜索列表原样返回且不计算搜索候选。其他工具名仍可使用 JSON、表格和日志压缩。 精确名称 Grep 始终排除这些域,以保留全部已收到命中;关闭路径共享不会恢复此功能引入前 自定义 Grep 工具的 JSON、表格和日志派发。全局压缩开关仍控制已开启域的 dry-run。 整任务节省取决于工作负载;保留全部收到的字节并不保证后续工具调用更少或总 Token 用量更低。

首行为固定格式声明,后续 File= 行包含 JSON 编码的路径;数据行必以 ASCII 数字和 : 开头, 因此不可能被误认为文件头。还原时在每个数据行前拼接当前解码路径与 :,保留原始行尾; 同一路径在非连续位置出现时会生成新的文件头。

解包的 Grep 列表在统计中记作 api_response,而非 file_content,因为它是筛选后的工具响应, 不是权威文件副本。按来源分组的历史查询因此存在版本边界。Core 将精确工具名 Grep 视为 仅适用搜索压缩的工具;即使搜索路径共享关闭,也不会转入 JSON、表格或日志压缩。SDK 调用者 仅应对符合此搜索契约的工具使用该名称。

Stats 查询

TokenlessStats 是只读的公开查询客户端,复用 CLI 相同的 Rust StatsRecorderstats.db Schema。它提供 typed 的状态、汇总、最近记录、记录详情、结构化 Diff 和 baseline 对比结果。TokenlessSdk.stats 会针对 Runtime 数据目录延迟创建该客户端, 因此 Stats 数据库损坏不会改变生命周期初始化或压缩侧的 fail-open 行为。这里的只读是 指公开操作;为与 CLI 保持一致,打开客户端时可能创建或迁移 stats.db,所以数据目录 必须可写。

Summary、List 和 Compare 只开放指标;记录详情以及 Record/Tool-use 的详细 Diff 可能 包含保存的工具内容,并继续遵守现有 1 MiB 输入和 500 行 Diff 上限。Token 数量是估算值, Runtime 只记录候选确实减少估算 Token 的操作。Summary 或 Compare 未指定 Limit 时, 使用 Recorder 的 10,000 条记录上限;Session 和 Tool-use Diff 同样最多加载最近 10,000 条匹配记录。Compare 预期先传入 dry-run Baseline Session,再传入启用 Tokenless 的 Session;客户端不会推断或强制这两种模式。Python API 不清空数据,也不修改全局记录 开关。

打包与验证

make python-wheel 会构建固定版本 RTK,把它暂存为 anolisa_tokenless/_bin/rtk,再生成 CPython 3.11 stable ABI 平台 Wheel。跨平台构建器 可以通过 PYTHON_RTK_BINARY 指定为同一 Wheel 目标构建的 RTK 文件。 make test-python-runtime 会在全新环境安装 Wheel,并在不依赖系统 RTK 的条件下验证 四个生命周期和 Stats 查询。

anolisa-tokenless-agentscope 支持 AgentScope 1.0.11 至 1.0.x 和 2.0.x。1.x Adapter 使用 Tokenless Toolkit、模型代理和公开的实例 Hook;2.x Adapter 使用 on_model_callon_acting。2.0.0 在配对的 Middleware/Tool 中保存 marker,后续版本还会把它持久化 到 AgentState.middle_context。两者都开放完整 SDK;2.0.0 支持直接构造 Agent,App 集成从 2.0.1 开始。内置工具具有显式契约;应用必须为每个自定义工具注册 ToolContract, 确保 ContentOrigin 不从输出文本推断。