dsh headless 怎么跑一次性任务?DeepSeek Harness 输出流与退出码
dsh headless 是一次性任务模式:启动一个全新 Agent,提交任务,等它完全停稳并 flush 会话,然后把最终文本写到 stdout、把推理过程写到 stderr,最后用退出码告诉你这轮有没有正常完成。 它不监听端口,也不挂载浏览器客户端,所以特别适合 CI、定时脚本和“跑完就走”的自动化。真正需要记住的是输出契约:stdout 只有答案,stderr 是过程,退出码看终止原因。
DeepSeek Harness:它和 web、sdk 的边界
headless 不是“没有界面的 web”,而是一条独立的一次性执行路径。 对比如下:(来源)
| 模式 | 生命周期 | 是否监听端口 | 典型用途 |
|---|---|---|---|
dsh web | 常驻 | 是,默认 3080 | 人机交互 |
dsh --profile headless | 一次任务后退出 | 否 | CI、脚本、批处理 |
dsh --profile sdk | 由客户端控制 | 否,走 stdio | 程序内嵌 |
dsh --profile sdk-minimal | 由客户端控制 | 否,走 stdio | 极简 SDK 运行时 |
headless 不挂载浏览器 Connection、HTTP 服务器、Web 运行时或浏览器客户端。也就是说,它不会因为端口被占用而启动失败,也不会留下一个后台服务等你关。
DeepSeek Harness:一次任务跑完发生了什么
headless 的执行顺序是固定的:建 Agent → 提交任务 → 等停稳 → flush → 从持久事件里推导结果。 展开看:(来源)
- 创建全新 Agent — 通过核心注册表创建一个持久化 Agent。预期:本次任务有独立的会话记录,不复用上一次的对话。
- 提交任务文本 — 位置参数就是任务内容。预期:Agent 开始按正常轮次执行。
- 等待完全停稳 — 不是“模型停止输出”就结束,而是等 Agent 生命周期进入空闲。预期:工具调用、子任务与收尾都完成。
- flush 会话 — 把持久化缓冲写入磁盘。预期:后续读取到的是完整事件区间,不是内存里的半截状态。
- 推导最终结果 — 取最后一个非空 assistant 文本与最后一个
turn/end原因。预期:stdout 得到答案,退出码反映终止原因。
这也解释了一个常见现象:任务看起来“卡住”时,可能不是模型没回复,而是 Agent 还在等工具或子任务停稳。headless 不会在中途把半成品当最终结果输出。
DeepSeek Harness:stdout、stderr 与退出码的契约
stdout 只放最终答案,stderr 放推理,退出码放完成状态;三者不要混用。 契约如下:(来源)
| 通道 | 内容 | 使用建议 |
|---|---|---|
| stdout | 最后一个非空 assistant 文本 | 直接重定向到文件或管道 |
| stderr | dsh: reasoning: 下的推理增量 | 记录日志,不要当答案解析 |
| 退出码 0 | turn/end 原因为 completed | 视为成功 |
| 退出码 1 | 其他终止原因或执行失败 | 视为失败,保留 stderr 排查 |
调用形态:
dsh --profile headless "run the tests and summarize failures" \
> /tmp/dsh-answer.txt \
2> /tmp/dsh-reasoning.log
- 先看退出码 —
echo $?。预期:0 才继续消费答案;1 时先看 stderr。 - 再读 stdout — 只取最终文本。预期:不包含推理标题、工具日志或进度条。
- 最后看 stderr — 推理内容与错误都在这里。预期:能区分“模型想了很久”和“工具执行失败”。
不要用 2>&1 把两个流合并后再解析;一旦合并,stdout 就不再是纯答案。
DeepSeek Harness:三种 CI 用法
headless 最适合“一次输入、一次输出、一个退出码”的自动化;不同场景只需要换外层包装。 三种常见写法:(来源)
- 直接命令行 —
dsh --profile headless "$PROMPT"。预期:适合简单任务,外层用 shell 判断退出码。 - 包一层脚本 — 脚本里固定 workspace 与
DSH_HOME,把 stdout 写入制品。预期:不同 CI 任务之间隔离配置与会话。 - 定时触发 — 由 cron 或 CI 调度器触发,每次生成独立 session。预期:避免复用同一段对话导致上下文越滚越大。
如果任务需要继续上一段对话,headless 不是合适入口;它每次创建全新 Agent。需要续跑时用 SDK 或显式复用 session 的模式。
DeepSeek Harness:常见坑与排查
headless 的问题大多不是“模型不干活”,而是输出契约被误读。 四个高频坑:(来源)
- 把 stderr 当答案 — 推理增量也在 stderr,解析时会混入思考文本。预期:只从 stdout 取答案。
- 只看文本不看退出码 — 有输出不代表成功,终止原因可能是取消或错误。预期:退出码非 0 时按失败处理。
- 任务文本为空 — 没有位置参数就是用法错误。预期:调用前检查变量是否为空。
- 忘记隔离 home — 多次任务共用同一 home 会共享 profile、插件与会话目录。预期:CI 里显式指定
DSH_HOME。
排查顺序建议:先看退出码,再看 stderr 末尾的错误,最后才看 stdout 内容是否符合预期。反过来的话,很容易被一段“看起来像答案”的文本带偏。
DeepSeek Harness:信号、退出与资源释放
headless 收到 SIGINT 或 SIGTERM 时,会先 dispose 挂载的根节点再退出,不是直接杀进程。 这条行为决定了自动化里怎么“优雅取消”:(来源)
- 发 SIGTERM — 让进程有机会释放资源、结束在途工具调用。预期:进程退出,会话日志保留到已 flush 的位置。
- 不要立刻 SIGKILL — 强杀可能留下未 flush 的会话尾部。预期:需要硬停时,先给一次 SIGTERM 的窗口。
- 按退出码判断 — 被信号终止通常不是 0;脚本应把它当失败或“未完成”处理。预期:不会把取消误判成成功。
headless 不挂载 HTTP 服务器与浏览器客户端,所以没有“端口没释放”的问题;它需要释放的是会话持久化与工具子进程。
DeepSeek Harness 常见问题
Q:headless 能不能开 Web UI 端口?
不能。它不挂载 HTTP 服务器,也不打开监听端口;需要界面就用 dsh web。
Q:一次 headless 会不会留下会话文件?
会。它会创建持久化 Agent 并 flush 会话,所以 $DSH_HOME/sessions 下会有记录;需要清理时按会话保留策略处理。
Q:能不能把 headless 当“无界面常驻服务”? 不合适。它是一次性任务模式,跑完就退出;常驻服务应该用 web 或 SDK 客户端。
一句话收束: headless 的价值在于契约清晰——stdout 是答案、stderr 是过程、退出码是结论;按这三条用,它就比“截屏式自动化”可靠得多。
常见问题
DeepSeek Harness 里,dsh headless 是一次性任务模式:启动、提交任务、等 Agent 完全停稳、flush 会话,然后退出;它不挂载浏览器 Connection、HTTP 服务器或 Web 运行时,也不打开监听端口。dsh web 则是常驻的 Web UI。
DeepSeek Harness 里,stdout 只打印最终 assistant 文本;非空的提供方 reasoning 增量会写到 stderr,并带 dsh: reasoning: 标题。没有推理内容的成功响应会让 stderr 保持为空。
DeepSeek Harness 里,退出码看的是最终 turn/end 原因,不是有没有文本。只有原因为 completed 才返回 0;被取消、报错、达到其他终止原因时即使有部分输出也会返回 1。脚本应同时判断退出码与 stdout。
DeepSeek Harness 里,会按用法错误处理。headless 的任务文本是位置参数,没有任务就不是一次有效调用;它不会进入交互式等待,也不会默认读取某个文件。
DeepSeek Harness 里,适合。它不监听端口、只输出最终文本、用退出码表达完成状态,天然适合 CI。需要注意的是每次调用都会创建一个持久化 Agent 会话,反复跑要规划好 session 与 workspace 的隔离。
相关术语
- headless
- headless 是 DeepSeek Harness 的一次性任务 profile,用 dsh --profile headless <任务> 启动;它运行一个全新持久化 Agent,等待完全停稳并 flush 会话后退出。— DeepSeek Harness 官方参考 - dsh CLI 行为
- turn/end
- turn/end 是 DeepSeek Harness 会话日志中标记一轮结束的持久事件,带终止原因;headless 用最后一个 turn/end 的原因决定进程退出码。— DeepSeek Harness 官方参考 - dsh CLI 行为
- flush
- flush 是 DeepSeek Harness 把会话日志与持久化缓冲写到磁盘的动作。headless 在退出前会对会话执行 flush,确保最终文本来自已持久化的事件区间。— DeepSeek Harness 官方参考 - dsh CLI 行为
- reasoning 增量
- reasoning 增量是模型思考流的分片,与最终可见文本分开。headless 把它们写到 stderr,避免污染只承载最终答案的 stdout。— DeepSeek Harness 官方参考 - dsh CLI 行为
来源
- DeepSeek Harness 官方参考 - dsh CLI 行为· deepseek-ai
- DeepSeek Harness 官方参考 - 子进程· deepseek-ai