在 DeepSeek Harness 中运行其他 Agent Harness
dsh(DeepSeek Harness)是目前扩展性最好的开源 Agent Harness 之一——"万物皆插件"。
但你可能还想在某个对话里用 Claude Code、Codex CLI 或 Gemini CLI 的完整能力(它们自带工具、权限系统和模型接入)。
dsh-host 让 dsh 的模型选择器里直接出现这些外部 agent:每个对话选一个 agent,整个对话由它执行,对话历史、流式输出、用量统计都走 dsh 原生体验。
还带官方品牌图标:内置一个 Web 客户端插件(dsh-host-icons),在模型选择器、输入框的当前模型标签、以及侧边栏会话列表每一行注入各 agent 的品牌图标(Claude 星芒、OpenAI、Gemini、Qwen、DeepSeek 鲸鱼等)——codex-host 同款的视觉体验。
中途切换 agent 的语义:codex-host 里线程与 harness 创建时锁定(一对一);dsh 本身允许会话中途换模型,所以会话行的图标显示 next——下一条消息将由谁执行,切换后实时更新;当 next ≠ lastUsed(刚切换过)时,悬停行会提示"上次执行: X · 下一条将使用: Y",切换不丢信息。
灵感与模式来自 codex-host(在 Codex Desktop 中运行其他 harness)——dsh-host 把宿主换成了 dsh。
本项目在 dsh 0.1.2-alpha.2(Windows x64, Node 24)上完成过端到端验证:
dsh plugin --profile <name> add ./dsh-host安装 bundle 插件;- profile patch 配置 agent 路由并覆盖
agent-default-model; dsh --profile <name> "任务"headless 运行 —— dsh agent loop 组装的完整对话上下文(4.4KB 转录)经 stdin 交给外部 agent CLI,流式回复回到 dsh 打印,退出码 0。
npm test 提供 7 项离线冒烟测试(三种输出模式、超时、非零退出、路由解析、多轮历史)。
dsh 的 agent loop 每一步都会组装一个"模型请求"并发给当前对话选定的 LLM provider。dsh-host 实现了一个外部 agent 适配器(ExternalAgentAdapter),注册在 dsh 的 ctx.llm provider 注册表上:
dsh 会话(provider = claude-code)
└─ dsh agent loop 组装请求(完整对话历史)
└─ ExternalAgentAdapter.stream()
├─ 在会话工作目录里 spawn 外部 agent CLI
├─ 输入:transcript 渲染 或 stream-json 消息(按 agent 而定)
├─ 输出解析:流式文本 / Claude stream-json / Codex JSONL
└─ 还原为 dsh 的 StreamChunk(文本增量、reasoning、usage、finish)
也就是说:外部 agent 是一个"模型"。dsh 的会话日志、Web UI、压缩、标题生成全部照常工作,只是"模型"背后站着的是一整个 agent harness。
两个设计上的边界(都是有意为之):
- dsh 的系统提示词和工具 schema 不转发给外部 agent——子 agent 有自己的人设与工具(
forwardSystemPrompt: true可把 dsh 系统提示词附带进转录文本)。 - 外部 agent 自己执行自己的工具(文件编辑、命令等发生在真实工作目录),dsh 侧看到的是它的文字叙述与最终回复。
要求:Node.js ≥ 22,dsh(npx @deepseek-ai/dsh web)。
# 1. 获取本项目(仓库已带预编译产物,无需构建)
git clone <this-repo> dsh-host
# 2. 安装进一个 dsh profile(首次会自动创建 profile 并叠上 dsh-base)
dsh plugin --profile host add ./dsh-host
# 3. 安装品牌图标客户端插件(Web UI 模型选择器里显示各 agent 官方图标)
dsh plugin --profile host add ./dsh-host/client
# 4. 按"配置"一节写入 agent 路由,然后启动
dsh --profile host两个 add 都要做:第一个是宿主侧适配器 bundle,第二个是 Web 客户端图标插件(纯浏览器端,不参与宿主组合)。跳过第 3 步功能不受影响,只是选择器里没有图标。
注意:同一个 profile 里不要同时安装
dsh-headless和dsh-web-appbundle(两者的补丁都会插入code-runtime行,id 冲突会导致启动失败)。
在 profile 的 cordis.patch.yml($DSH_HOME/profiles/<name>/cordis.patch.yml)里定位到 id: dsh-host 那一行写入配置,保存即生效(live reload)。每个 agent 条目的键名就是模型选择器里的 provider 名:
- id: dsh-host
config:
agents:
claude-code:
preset: claude-code # 内置预设,开箱即用
permissionMode: acceptEdits
codex:
preset: codex
permissionMode: full-auto
gemini:
preset: gemini-cli
my-agent: # 任意 CLI 都能接
command: ["myagent", "run"]
input: transcript # transcript | stream-json
output: text # text | stream-json | codex-jsonl
promptVia: argv # argv | stdin | stdin-dash
models:
- id: fast
name: My Agent (Fast)
args: ["--fast"]如果想让某个 profile 默认就用某个外部 agent(headless / SDK 场景),同时覆盖默认模型行:
- id: agent-default-model
config:
provider: claude-code
model: default| 预设 | 命令 | 输入/输出 | 说明 |
|---|---|---|---|
claude-code |
claude |
stream-json / stream-json | 增量流式;自动 --resume 延续 Claude 自己的会话;精确 usage |
codex |
codex exec --json - |
transcript / codex-jsonl | 宽容解析(兼容多版本事件格式);usage 最佳努力 |
gemini-cli |
gemini -p |
transcript / text | 纯文本流式 |
qwen-code |
qwen -p |
transcript / text | 同 gemini-cli |
opencode |
opencode run |
transcript / text | 纯文本流式 |
图标:路由名或显示名包含 claude / codex / gemini / qwen / opencode / deepseek 时,模型选择器自动显示对应品牌图标(图标 path 来自 Simple Icons,CC0;品牌归属各自所有者)。自定义 agent 想要图标,让路由名或显示名带上上述关键词即可。
预设只是"默认值":command、权限模式、模型变体等都可以在路由里覆盖。例如 Windows 上把 claude 换成 cmd 包装:
agents:
claude-code:
preset: claude-code
command: ["cmd", "/c", "claude"]
permissionMode: acceptEdits权限提示:headless 运行没有交互审批。
claude-code预设默认权限档为default,未授权的工具调用会被 Claude Code 拒绝;要在 dsh 对话里让它能改文件,配permissionMode: acceptEdits,完全放开则用bypassPermissions(自担风险)。codex 预设同理(full-auto/danger)。
| 字段 | 说明 |
|---|---|
preset |
叠加的内置预设 |
command / args / extraArgs |
可执行文件与参数(argv 数组,不走 shell) |
input |
transcript:整段对话渲染成单个提示词;stream-json:Claude 协议 |
output |
text 原样流式;stream-json / codex-jsonl 结构化解析 |
promptVia |
提示词投递:argv(末尾参数)/ stdin / stdin-dash |
permissionMode |
预设的权限档(见各预设 permissionArgs) |
models |
模型变体列表(映射到 agent 自己的 --model,带 contextWindow 展示) |
env |
注入子进程的环境变量(叠加在凭证擦除后的环境上) |
cwd |
工作目录覆盖(默认:会话的工作目录) |
timeoutMs / graceMs |
整体超时(默认 10 分钟)/ 终止宽限 |
forwardSystemPrompt |
把 dsh 系统提示词附进转录(默认 false) |
仓库自带 demo/fake-agent.mjs。把它配成一个 agent 路由(见上方 my-agent 示例,command 换成 ["node", "<repo>/demo/fake-agent.mjs"]),就能在任何对话里验证 dsh-host 链路。
npm test 跑离线冒烟测试;npm run build 重新编译(esbuild 单依赖)。
- usage:Claude Code 精确;Codex 最佳努力;
text模式按字符数估算(约 4 字符/Token)。 - 图标:注入点为模型选择弹层、菜单当前值行、输入框触发按钮、侧边栏会话行;按名称文本匹配,因此自定义 agent 需要让名字包含品牌关键词才显示图标。会话行数据来自 dsh 的
modelSelection会话投影(客户端列表快照自带,无额外请求)。 - 工具可视化:外部 agent 的工具调用不在 dsh 里显示为工具卡片(它们由 agent 本地执行);后续可把常见工具事件映射为 dsh 工具项。
- 审批打通:外部 agent 的权限系统独立于 dsh 的审批流(通过预设的
permissionMode控制)。 - codex 跨轮上下文:codex 路由走 transcript 重放(无原生会话续接);claude-code 已支持原生
--resume。 - Web 设置页集成:目前配置走 profile patch 行;接入 dsh settings 服务的动态配置是下一步。
- Windows:argv 不走 shell,npm 安装的
.cmdshim 需要cmd /c包装(见上例)。
- deepseek-ai/deepseek-harness —— 宿主与插件体系
- BytePioneer-AI/codex-host —— "每个对话选一个 agent" 的产品形态
MIT