前言¶
在 DSH / Claude Code 里用 subagent 做路由、分类或结构化抽取时,常见做法是依赖提示词或 response_format 约束 JSON 形状。DSH 侧 subagent 经代理走 Anthropic /v1/messages 端点;资料中的实测表明,该端点对 response_format(json_schema)会静默忽略,模型仍可能输出自由文本。不同 subagent 若还要各自不同的输出结构,单靠一套全局格式更难落地。
下面介绍的 dsh-structured-output(维护者 dd2003-460)在代理层改用 强制工具调用:把输出形状写进单个 function 的 input_schema,用 tool_choice 锁死;代理再把 tool_use 剥壳还原成纯文本 JSON,调用方当普通文本读即可。模型仍只有一个,每个 agent 在注册表 agents.json 里配不同 schema。
这是什么¶
- 定位:DSH / Claude Code 工作流插件——把 subagent 输出焊死成固定结构(choice / open_choice / json 等),按 agent 区分 schema。
- 来源:GitHub 仓库,许可证 MIT;
package.json版本 0.1.0。 - 社区目录:SkillHub 插件页(DSH Community Market 独立收录,与 DeepSeek / 幻方无官方从属关系)。
为什么用强制工具调用¶
README 在 1Cat vLLM 1.5.0 / Qwen3-27B-W8A16(2026-10-25)上对比过几种机制:在 Anthropic /v1/messages 上,response_format、guided_json / guided_choice、extra_body 透传均不生效或无效;强制工具调用(tool_choice 锁单个 function)在该端点与 OpenAI /v1/chat/completions 上均可生效。本插件因此不依赖 response_format,而把「输出形状」定义为工具的参数 schema。
核心能力¶
仓库内置几种典型形状(均在 agents.json 可改、可扩):
| 键名 | 用途 |
|---|---|
router |
固定枚举 choice:只能从给定候选选一个 |
advisor |
open_choice:label / 理由 / 汇总自由生成,每条带 confidence(0~1) |
brief |
advisor 精简版:最多 3 条、理由与 summary 各限长——subagent 快速给结论 |
ticket |
固定 json:字段受 enum 等约束 |
| (无标记) | free:不带 schema 标识的请求不受影响,为默认行为 |
另含 DSH skill structured-dispatch:市场安装后由 DSH 自动发现并加载,主 agent 可按 SKILL.md 触发条件派发带 schema 的 subagent;未打代理补丁时 skill 退化为提示词级软约束。
安装与启用¶
插件以当前 DSH 进程权限运行;安装前请自行查看仓库源码与 MIT 许可证。
方式一(推荐):DSH 市场¶
仓库已打 dsh-plugin topic,Community Market CI 约每 2 小时自动收录。可在 DSH 内打开 Community Market(或 1024Store / dshfind),搜索 dsh-structured-output;或命令行:
dsh plugin add dsh-structured-output
装完后 skill 会自动加载,主 agent 按 SKILL.md 派发 subagent,无需额外手动注册 skill。
方式二:代理补丁(硬约束)¶
要让输出在转发层真正被锁死(而不只是 skill 软引导),需把补丁打到已有的 claude-vllm-proxy:
cd dsh-structured-output
node install.mjs
# 或指定代理文件:
PROXY_TARGET=/path/to/proxy.mjs node install.mjs
脚本会把 lib/structured.mjs 与 agents.json 复制到代理目录旁的 structured/,并 patch 默认 ~/.claude-vllm-proxy/proxy.mjs(自动备份)。重启代理后生效,例如:
launchctl kickstart -k gui/$UID/com.a1-6.claude-vllm-proxy
也可重启 DSH。卸载:node install.mjs --uninstall。重复安装幂等;改完仓库内 agents.json 后需再跑 node install.mjs 刷新复制文件,再重启代理(无需 --uninstall)。
典型用法¶
让某个 agent 走结构化输出¶
两种识别方式(按优先级):
- model 后缀(Claude Code subagent 推荐):在 subagent frontmatter 的
model后加__schema=<key>,客户端/代理会剥掉后缀再发给 vLLM。
# .claude/agents/router.md 的 frontmatter
model: qwen3.8-27b-w8a16__schema=router
- HTTP 头:
X-Agent-Name: <key>(自研 harness / 客户端)。
不带上述标识的请求保持自由输出,不进入插件逻辑。
新增或修改 agent 形状¶
编辑根目录(或代理旁 structured/)下的 agents.json。每个 key 对应一个 agent,input_schema 即 Anthropic 原生 tool schema。固定候选用 enum;开放内容用 type: string 不写 enum。confidence 的 minimum/maximum 为软约束,插件会对数值 clamp 到 [0,1]。
路由示例:
{
"router": {
"description": "二/多分类路由动作",
"input_schema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["search", "calculator", "translate", "refund"]
}
},
"required": ["action"]
}
}
}
端到端测试¶
安装代理补丁并启动代理后:
BASE_URL=http://localhost:8787 node test-structured.mjs
预期:advisor 返回含 options[] 与 confidence 的合法 JSON;router 的 action 落在 enum 内;普通请求仍为自由文本。
适用场景与注意¶
适合:同一基座模型下,多 subagent 各自固定输出形状——分类路由、带置信度的方案列表、固定字段工单 JSON;主 agent 只需「决策 / 分类 / 抽取」时,README 建议派发结构化 subagent 而非在主对话里长文生成,以减轻 decode 与 KV 占用。
限制(仓库 README 明确列出):
- 调研型 two-phase(先自由调工具、再结构化汇报):在 Anthropic
/v1/messages上本插件强制单个输出工具,无法与多个真实工具并行;需两段式模式可参考仓库内同思路的 Python harness(OpenAI 端点 +response_format)。 - 强制工具模式下会关闭 thinking,避免思考文本混入工具参数。
- 只改代理转发逻辑,不改模型权重;并发行为与原代理一致。
结尾¶
dsh-structured-output 把「按 agent 固定 schema」落在注册表与代理强制工具调用上,并与 DSH skill 派发衔接。需要安装说明与 schema 示例时,可看 SkillHub 目录页 与 GitHub README。