快速上手
sift 以 npm 包 @agent-context/sift 提供 Node.js API,核心为纯 Rust(napi-rs 绑定)。安装时自动命中当前平台的二进制子包。适合"上下文里塞了大量机器产出"的场景——这些内容 token 多、冗余高,但真正对任务有用的信息密度低。
安装
npm install @agent-context/sift直接接入 Coding Agent
sift-plugins 已为 Codex、Pi、OpenCode、Claude Code 和 DeepSeek Harness 提供现成适配器。无需自己编写 hook:适配器会自动压缩新产生的工具输出,并注册 sift_retrieve,让 Agent 在需要时取回 stash 原文。
Codex CLI / App
当前预览版要求 Codex CLI ≥ 0.145.0 与本机 Node.js ≥ 18。CLI 和桌面 App 共用本地主机上的插件、hook 与 MCP 配置:
codex plugin marketplace add agents-sdk/sift-plugins
codex plugin add codex-sift-plugin@agent-contextPi
pi install npm:@agent-context/pi-siftOpenCode
要求 OpenCode ≥ 1.18.26 且 < 2。推荐使用 CLI 安装,它会同时注册压缩服务与 TUI token 统计入口:
opencode plugin @agent-context/opencode-siftClaude Code
@agent-context/claude-code-sift 要求 Claude Code ≥ 2.1 且本机 Node.js ≥ 18。在 Claude Code 中依次执行:
/plugin marketplace add agents-sdk/sift-plugins
/plugin install claude-code-sift@agent-context插件安装后默认启用,通过 PostToolUse hook 压缩工具输出,并由内置 MCP server 提供 sift_retrieve。
DeepSeek Harness
要求 Node.js ^22.19 或 ≥ 24.2。把插件安装到需要启用的 dsh profile,然后启动对应宿主:
dsh plugin --profile web add @agent-context/dsh-sift
dsh web完整安装、配置、stash 存储与排障说明见 agents-sdk/sift-plugins。
最小示例
import { createSift, siftRequest, siftText, retrieve, retrieveLines } from "@agent-context/sift";
// 1. 压缩请求体:自动检测 Anthropic /v1/messages、
// OpenAI Chat Completions、OpenAI Responses 三种格式
const { body, changed, tokensSaved } = siftRequest(requestBody, "用户当前的问题");
// 2. 或压缩源码;折叠点直接指向落盘 stash 文件
const r = siftText(fileContent, "error mismatched");
// // ... 30 lines omitted from file "/home/agent/.sift/stash/HASH", starting at line 32
if (r.lossy) {
// 有损:原文已入 stash store,输出尾部带 «stash:HASH» 标记
const original = retrieve(r.stashKey!);
// 若输出提示给出省略行范围,也可以只取回所需分片
const fragment = retrieveLines(r.stashKey!, 120, 80);
}指定 stash 目录
直接导入的 siftRequest、siftText、retrieve 和 retrieveLines 使用共享的默认 store:优先读取 SIFT_STASH_DIR,其次是 ~/.sift/stash,最后才回退到系统临时目录。如果应用需要隔离租户、任务或测试数据,用 createSift 创建绑定到指定目录的实例:
import { createSift } from "@agent-context/sift";
const sift = createSift({
stashDir: "/var/lib/my-app/sift-stash",
});
const result = sift.siftText(toolOutput, "error mismatched");
const original = result.stashKey
? sift.retrieve(result.stashKey)
: null;stashDir 必须是非空字符串;相对路径按调用 createSift 时的工作目录解析。每次调用都会创建独立实例,所以同一 Node.js 进程可以同时使用多个 stash 目录。压缩和恢复要使用同一个实例,顶层 retrieve 不会读取实例的独立目录。
典型场景
Agent 的工具输出
编码 Agent 每轮都会往上下文里塞构建日志、grep 结果、git diff。几轮之后,工具输出占了绝大部分 token,而且旧轮次的输出早就没用了。
for (const step of agentSteps) {
const out = await runTool(step);
// 送进模型前先压缩,query 用当前任务描述
const r = siftText(out, step.intent);
messages.push({ role: "tool", content: r.text });
if (r.lossy) keepForRecovery(r.stashKey);
}要点:query(当前意图)帮助相关性筛选的压缩器保留关键行;纯文本也会把 query 纳入 BM25 相关性评分。
长对话的历史消息
对话越长,每轮的输入成本越高。在发送请求前对整个 body 跑一遍 compress,早期消息里的日志、JSON、diff 会被压缩,而最近的轮次与冻结前缀保持原样。
// 发送前一步,自动检测 Anthropic / OpenAI 格式
const { body, tokensSaved, frozenMessages } = siftRequest(requestBody, userQuestion);
await fetch("/v1/messages", { method: "POST", body: JSON.stringify(body) });要点:cache_control 以下的消息是缓存锚点,sift 一个字节都不动,不会破坏你的 prompt cache 命中。
把大文件喂给 LLM
分析线上问题、读监控数据时,原始文件往往几十 KB 起步。先 siftText 再送入:
- 监控 / 导出的 JSON 对象与数组:同构记录转 CSV-schema,异构记录可分桶;任意深度的数组和字符串化 JSON 递归紧凑化,超过 256 B 的 opaque 值可独立取回;
- 构建 / 测试日志:错误与堆栈全保留,重复 warning 折叠成一条;
- git diff:lockfile / 纯空白变化摘要,hunk 采样,改动行保留;
- 会议纪要等长文本:按相关性、位置和显著信息抽取代表句段,并抑制近重复内容;完整原文可从 stash 恢复。
API 一览
createSift({ stashDir })
创建绑定到独立 stash 目录的 API 实例。实例提供 siftRequest、siftText、retrieve、retrieveLines、detectContentType 和 detectRequestFormat;不影响直接导入的顶层 API 及其默认目录逻辑。
siftRequest(body, query?)
压缩请求 body(就地透传或压缩),返回:
| 字段 | 说明 |
|---|---|
body | 压缩后的请求 body(格式与输入一致) |
changed | 是否发生了实际压缩 |
blocksExamined / blocksCompressed / blocksReverted | 检查 / 压缩 / 因 token 校验回退的 text block 数 |
frozenMessages | 冻结前缀消息条数(cache 锚点,未被触碰;OpenAI 格式恒为 0) |
stashStored | 写入 stash store 的原文条数 |
tokensSaved | 估算节省的 token 数 |
siftText(text, query?, sourcePath?)
压缩单个字符串(把工具输出原文送进任意 API 之前),返回 text / changed / lossy / stashKey / tokensSaved。使用落盘 stash 时,源码、搜索结果、日志以及显式保守模式的整行纯文本可在省略位置输出 [... 30 lines omitted from file "/home/agent/.sift/stash/HASH", starting at line 32],代码使用注释形式。文件是完整原文,起始行从 1 计数,不是搜索命中源码的行号。默认纯文本按句子抽取,不伪造行范围,通过末尾 stash 标记恢复。Git Diff 在逐段绝对路径会抵消收益时改用紧凑文件/hunk 汇总。可选的 sourcePath 仅用于按扩展名选择 8 种源码 grammar。单 block 最小 512 字节才参与压缩。
无损 CSV-schema / minify 不产生 stash 或省略提示。JSON 结构采样、行内片段、标签保护造成映射变化、非本地 store 等情况暂不输出文件行提示。纯文本默认按 query 相关性、位置、显著信息和近重复抑制进行抽取,保留的句段逐字来自原文。
日志首个非空行、可识别的命令回显(如 $ cargo build、shell tracing、npm script、PowerShell 提示符)及显式续行强制保留,不会被普通日志行数预算截掉或隐藏在模板中。能从 stash 恢复不等于允许省略执行命令。
retrieve(key)
按 stashKey 从 stash store 取回有损压缩的原文,端到端无损。
retrieveLines(key, startLine, lineCount)
按 stash 原文的 1-based 行号读取连续分片,单次最多 1000 行;返回 text / startLine / lineCount / totalLines / hasMore。这是非本地 stash 或文件工具不可用时的备选;代码内联提示本身不要求调用这个 API。
detectContentType(text) / detectRequestFormat(body)
类型探测:返回内容类型(JSON 对象或数组,也识别连续对象与 JSON 为主体的轻量 wrapper / 构建日志 / 搜索结果 / git diff / 源代码 / 纯文本 / HTML / YAML、TOML、INI 结构化配置 / CSV、TSV、Markdown 表格)或请求格式(anthropic / chat_completions / responses)。
最佳实践
- 按需传 query:用户当前的问题、Agent 当前步骤的意图可帮助相关性筛选,纯文本默认也会使用 query。
- 按原文坐标读取:模型只追问局部时,优先用 Agent 已有的文件分片读取能力;原文不可直接访问时,再用
retrieveLines从 stash 读取。需要全文时可用retrieve。 - 成对使用实例 API:通过
createSift压缩后,必须通过同一实例的retrieve恢复;顶层 API 和其他实例可能指向不同目录。 - 不用担心凭据被隐藏:压缩只发生在消息内部,对话结构、tool_use/tool_result 配对完整保留;API key 等高熵候选必须逐次留在可见输出中,否则该有损结果会回退。
- 短内容不用管:单 block 小于 512 字节不参与压缩,直接透传,零开销。