agent 树 token 预算管理。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:vibeinging/dsh-agent-budget
GitHub 来源的插件在安装时会在你的机器上执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
dsh-agent-budget 为一个活跃 agent(智能体)会话或其完整的本地后代树提供持久 Token 上限和绝对截止时间。它在每次可归属的 llm/stream 提供方调用尝试前预留额度,并在流结算后用提供方报告的用量替换估算值,因此并发子 agent 无法全部花费同一笔剩余额度。
该插件是在一个 Host 进程内运行的外置 DSH 组合包。硬预算会在 dispatch 前拒绝新的提供方调用尝试;它不是精确计费系统,也不会强制取消正在进行的工作。
决策记录:持久的 agent 树 token 准入。
提供内容
- 由 DSH Storage Domain 恢复的持久
session范围和本地后代树范围。 - 采用并发安全本地预留的软核算或硬准入。
- 可跨重启保留的绝对截止时间,以及已 dispatch 用量未知时的 fail-closed 恢复。
- 通过
/budget直接由人类控制;有意采用手动组合时可以启用可选的面向模型工具。 - 在有上限账户接近耗尽时降低
maxTokens的输出收敛机制。
安装
随附的 web 和 headless profile 提供本组合包所需的 Storage、Storage Domain、Token Meter 和命令服务。自定义 profile 必须自行提供这些服务。
从固定的 GitHub commit 安装
该仓库是私有的,且该包未发布到 npm registry。Git 和 pnpm 11.7.0 必须已经配置 GitHub 凭据。请固定到一个已经评审的 commit,不要安装内容会变化的分支;DSH Profile 是 pnpm workspace 根目录,因此必须使用 -w:
dsh plugin --profile web add -w github:dsh-external/dsh-agent-budget#<reviewed-commit>
仓库会提交其 lib/ 运行时入口,因此安装无需获得执行依赖构建脚本的权限。请检查组合后的配置项,然后启动 profile:
dsh --profile web --dump-config
dsh --profile web
从本地 checkout 安装
在本仓库根目录中,将该 checkout 链接到 profile。已提交的 lib/ 目录必须与 src/ 一致:
dsh plugin --profile web add -w .
dsh --profile web --dump-config
dsh --profile web
通过经过认证的人类命令路径,创建并查看第一个覆盖整棵树的硬预算:
/budget set 3 tree hard 2h
/budget
Token 数量以百万为单位,因此 3 表示 3,000,000 Token。额度追加和截止时间延长方法见完整的 /budget 命令参考。
使用以下命令移除该组合包及其 profile 依赖:
dsh plugin --profile web remove -w @deepseek-ai/dsh-agent-budget
组合包内容
cordis.patch.yml 会加载预算服务和 /budget 命令。该组合包会禁用面向模型的预算工具,并将直接人类控制交给 @deepseek-ai/dsh-agent-budget/command。它不会创建第二个共享 invariant 注册服务;手动组合可以把本包的 invariant 配套入口挂到已有注册服务上。其宿主 profile 必须提供 Storage 后端、ctx.storageDomain、ctx.tokenMeter 和共享命令服务。
手动组合
只有当组合包默认值不合适时,才使用手动组合。请先于预算插件加载 Storage 后端和 ctx.storageDomain。下方 JSON 后端是一种本地选择;其他 Storage Domain 后端可以替换它,而无需修改本包。只有在宿主尚未提供 ctx.invariants 时,才添加 @deepseek-ai/dsh-invariants。
- name: '@deepseek-ai/dsh-storage'
- name: '@deepseek-ai/dsh-storage-json'
config:
root: './.dsh/state'
- name: '@deepseek-ai/dsh-storage-domain'
config:
backend: json
- name: '@deepseek-ai/dsh-token-meter'
- name: '@deepseek-ai/dsh-invariants'
- name: '@deepseek-ai/dsh-agent-budget'
config:
fallbackMaxOutputTokens: 8192
guardedToolNames: [subagent, subagent_fork, workflow, ralph]
modelTools: true
- name: '@deepseek-ai/dsh-agent-budget/invariant'
fallbackMaxOutputTokens 是必填项,并且必须是正安全整数。当由 loop 构建且已设置预算的请求没有 maxTokens 时,插件会通过 agent/request 写入该上限,使 llm/stream 预留的数额明确记录在 request/header 中并可重建。带有归属会话的直接 llm/stream 调用也会在解析提供方之前获得同一上限。插件不会猜测提供方默认值,也不会把未知上限视为零。
warnRatio 和 warnMaxOutputTokens 构成一个可选的输出收敛层级;criticalRatio 和 criticalMaxOutputTokens 构成一个更严格的可选层级。剩余 Token 数除以 Token 总上限后,所得比例严格低于对应层级的比例时,该层级生效。生效层级会把 maxTokens 替换为请求当前上限与配置层级上限中的较小值,因此绝不会提高调用方的上限。每个层级的两个字段必须成对设置;同时配置两个层级时,警告层级的比例和上限都必须高于临界层级对应的值。仅设置截止时间的账户不会收紧输出上限。
guardedToolNames 列出会启动资源持有型工作的模型工具。硬预算账户耗尽、过期或处于不确定状态后,tools/pre-execute 会在这些工具的主体运行前拒绝对应名称。该策略保护标准工具路径;受信任插件直接调用工作流或 subagent 服务时,不会经过此工具策略。
modelTools 控制模型工具注册表中是否包含 set_agent_budget 和 get_agent_budget。对于有意让顶层 agent 处理用户直接提出的预算创建请求的手动组合,默认值为 true。如果预算由人类命令控制,请设为 false。本包组合会如此设置,因此余额和预算工具 schema 不会进入模型请求,也不会影响可复用的前缀缓存。
managementCommandName 是可选项且没有默认值。只有当组合提供名称完全一致的全小写人类命令时,才应设置此项;因 Token 硬限制或截止时间而拒绝请求时,错误信息会包含该命令专用的恢复指引。未设置时,服务会如实返回通用失败信息,而不是引用可能不存在的命令。
预算语义
| 项目 | 规则 |
|---|---|
| 范围 | session 只向已绑定的根会话计费;tree 还会绑定之后通过 session.header.parentSession 通知的后代 |
| Token 总量 | inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens;reasoningTokens 已包含在输出中,不再重复相加 |
| 截止时间 | wallTimeMs 只转换一次,得到绝对 deadlineAt;重启和重新加载不会延长它 |
| 软模式 | 记录预留与用量,但不拒绝工作 |
| 硬模式 | 当 spent + reserved + estimated input + max output 超过上限、截止时间已过,或之前已 dispatch 的用量不确定时,拒绝提供方调用尝试 |
| 缺失用量 | 将预留保留为 uncertain,绝不会按零结算 |
| 崩溃恢复 | domain 重新打开时,任何遗留的 reserved 或 dispatched 调用尝试都会变为 uncertain |
| 创建恢复 | 根绑定写入失败时回滚新账户;如果两次写入均失败,或进程在两次写入之间停止,启动时只会移除未发生任何变更且从未被引用的账户残留 |
「硬」表示硬请求准入,不是精确账单保证。输入使用 ctx.tokenMeter 给出的提供方无关估算值;提供方的分词方式可能不同,已 dispatch 的请求也可能产生从未返回 DSH 的用量。因此,插件报告 accuracy: reported | estimated | uncertain,而不是给出虚假的精确百分比。
每次账户变更都使用一条 Storage Domain 表记录的串行 update() 路径。本地并发请求会重新计算最新的 spent + reserved,因此只有未超过额度的请求才能完成预留。另一个持久的 SessionId -> BudgetId 表在进程重启后继续保留树归属。
创建账户时,如果绑定失败且账户回滚也失败,系统会同时报告这两项失败。启动时,系统只有在未绑定账户从未被引用、预留、结算或以其他方式修改的情况下才会删除它;任何已经发生变更却缺少根绑定的账户都会被视为损坏,导致插件初始化失败。
服务 API
ctx.agentBudget 提供策略服务。普通集成使用它创建和查看账户;拥有提供方调用尝试的集成使用显式生命周期方法。
const view = await ctx.agentBudget.create(agent, {
scope: 'tree',
enforcement: 'hard',
tokenLimit: 200_000,
wallTimeMs: 30 * 60_000,
})
ctx.agentBudget.get(agent)
const reservation = await ctx.agentBudget.reserve({
sessionId: agent.id,
provider: 'deepseek-official',
model: 'deepseek-v4-flash',
purpose: 'conversation',
estimatedInputTokens: 12_000,
maxOutputTokens: 8_000,
})
await ctx.agentBudget.increase(agent, {
additionalTokens: 1_000_000,
additionalWallTimeMs: 15 * 60_000,
})
账户不能替换或重置。只有账户的根 agent 精确实例才能增加 Token 上限或延长截止时间。追加额度可以恢复因耗尽或过期而停止的准入,但不会清除不确定用量。对于已不存在的调用尝试,markDispatched()、settle()、release() 和 markUncertain() 都是幂等的,使清理路径可以收敛,而不会重复计费。
开发与验证
lib/ 是提交到仓库的 Git 安装产物。项目 .npmrc 只选择私有 @deepseek-ai/* scope;pnpm 11 会读取 ${NPM_TOKEN} 认证映射,该映射来自受信任的用户级 ~/.npmrc。设置 NPM_TOKEN,运行 pnpm install --ignore-scripts,然后运行 pnpm run check。SDK 包固定使用经过评审的 0.0.1-rc.2 集合。不要把 DSH 源码 checkout 链接到本仓库。修改 src/ 后,请检查生成的 lib/ 差异,并保持运行时入口和声明一致。
无需 API key 即可运行确定性 Token 策略 eval:
pnpm run test:eval
该 eval 使用持久 JSON 存储驱动公开服务。7 个场景覆盖精确上限准入、超出 1 Token、并发预留、共享后代树账户、超出软上限后继续运行、用量缺失时 fail-closed,以及只允许根 agent 追加额度并重新开放已耗尽准入。npm test 还覆盖服务、命令、invariant、恢复、生命周期、上限收紧和 loader 组合。
模型体验
set_agent_budget
模型看到的内容
该工具为发起调用的顶层 agent 创建第一个预算。它仅能在该实时 agent 精确实例的活跃驱动器内成功,并且当前打开的轮次必须包含一条由宿主确认的 { kind: 'user' } 消息。插件生成的上下文、子 agent、直接注册表调用或之后的模型决策都不能自行获得更多额度。现有账户不能通过该工具增加、替换或重置。模型需要提供 scope、enforcement,以及 token_limit 或 wall_time_ms 中的至少一项;结果包含状态、总量、有上限时的剩余 token、存在时的截止时间和准确性。
创建成功结果
{"active":true,"budget_id":"budget-…","root_session_id":"main","scope":"tree","enforcement":"hard","token_limit":200000,"spent_tokens":0,"reserved_tokens":0,"remaining_tokens":200000,"status":"active","accuracy":"reported"}
Token 影响
启用 modelTools 时,每次请求都会携带稳定的 schema。每次调用的小型固定形状参数和结果都会保留在 Session 历史中。禁用后,该工具不会产生 schema 或调用历史。
KV Cache 影响
仅追加的工具调用和结果位于可复用请求前缀之后。余额变化不会重写之前的提示词内容。
get_agent_budget
模型看到的内容
该工具返回绑定到发起调用的 agent 精确实例的预算;没有预算时返回 { "active": false }。它是只读工具,并要求相同的实时驱动器身份检查,因此一个 agent 不能靠猜测 ID 查询另一个会话。
无预算结果
{"active":false}
Token 影响
启用 modelTools 时,每次请求都会携带稳定的 schema。每次查询会在 Session 历史中保留一个紧凑的状态对象。禁用后,该工具不会产生 schema 或调用历史。
KV Cache 影响
仅追加的工具调用和结果位于可复用请求前缀之后。插件不会在结算时重写系统提示词;准入失败则成为已记录的终止流错误。
已知限制与暂缓事项
- 核算只在一个 Harness 进程内保证原子性。在 Storage Domain 提供适合跨进程计数器的事务后端或比较并交换后端之前,两个进程不得写入同一账户。
- 没有
sessionId的调用、插件加载前已经存在但没有绑定的会话,以及没有本地 Session 的外部子 agent 都无法归属。 - 输入 token 在 dispatch 前估算。精确的提供方 token 计数 API 和带版本的价格表暂缓实现;金额预算、组织级预算、周期预算和收费工具预算均未实现。
- 标准工作流/subagent 模型工具受到保护,但受信任的直接服务调用可以绕过该路径。严格的树准入需要提供方调用尝试 ID,以及 subagent 和工作流的 pre-start seam。
- 截止时间会阻止新工作,但不会强行终止已 dispatch 的提供方调用或不配合的工具。
- 现有账户只能由根 agent 精确实例增加额度或延长时间。尚未实现降低额度、替换、暂停、重置、关闭或对账不确定用量。用量缺失会使硬预算继续 fail-closed。
链接
同类插件
hust-open-atom-club/oh-dsh★ 161
社区发行版:TUI、桌面端与 Web UI 统一体验,分层安装、一步到位。
Jayden-X-L/forkprobe★ 65
同一任务并行试跑多个技能,对比结果选出最优。
vlln/plugin-registry★ 33
插件生态基建:浏览器面板管理官方 repository 插件(0 patch)+ make-dsh-plugin 插件开发引导技能。
forrestchang/dsh-multica-runtime★ 28
让 dsh 运行时跑在 Multica 上。
DietCokewithSugar/dsh-user-experience★ 18
帮你发现项目中可能存在的用户体验问题:自动走查 React/TypeScript 源码,定位问题并给出具体优化建议。
omdsh-dev/dsh-plugin-check★ 17
插件健康检查:扫描清单协议/patch 格式/构建陷阱,零依赖只读。