deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
Keep DeepSeek V4 Pro deliberating deeply while its tools keep working.
Three experimental DeepSeek Harness (DSH) agent presets. The design premise comes from hands-on sessions with V4 Pro: its strongest reasoning — the "We …" chain — is highly conditional on the request surface, and the three modes below restore it at different moments of a conversation without ever taking the tools away:
| Mode | Directory | One line |
|---|---|---|
| Wire Think-Execute Standard | wire-think-standard/ |
every turn opens with a think step that keeps the tool catalog visible while the wire forbids invocation (tool_choice: "none"), then executes on the official route |
| Eternal Minimal | eternal-minimal/ |
the visible catalog stays the Minimal pair forever; heavier Standard tools run FOR REAL behind the dshx bash gateway |
| Combo Anchored | combo-anchored/ |
the combination package — think/execute split + deliberation gate + deliberation drip as three independent rows |
Not an official DeepSeek product. Sibling of
dsh-anchored-standard
(the first-request anchor modes); this repository holds the
whole-conversation deliberation mechanisms.
Observed on DeepSeek V4 Pro in our own sessions (the sibling repository documents the evaluation methodology):
tool_choice: "none") preserves the full planning context during
deliberation — the model still sees everything it will be allowed to use
— and leaves tools one parameter away from working again.The three modes operationalize these: wire-think-standard builds its think
steps on (2), eternal-minimal keeps the surface that (1) rewards for the
whole session while routing real tool execution behind a gateway, and
combo-anchored combines a zero-tool think opening, a (3)-style depth gate
for the first action, and a maintenance drip for the long middle of tool
loops.
| Mode | Directory | First model request | Anchor mechanism | Promotion signal | Cost |
|---|---|---|---|---|---|
| Wire Think-Execute Standard | wire-think-standard/ |
tools present, tool_choice: "none" on the wire |
sibling provider route per think step | per-turn: the steer itself | +1 model call/turn, tools-prefix cache switch |
| Eternal Minimal | eternal-minimal/ |
2 tools, forever | the visible catalog never grows; heavier tools run via the dshx bash gateway |
none (no phases) | none |
| Combo Anchored | combo-anchored/ |
0 tools, on every user turn | think/execute split + depth gate + deliberation drip as three independent rows | per-mechanism | +1 model call/turn |
Every mode directory is self-contained and installs alone under whatever id you copy it to (see Install).
str_replace_editor + the discovery tools (dev_tool_search,
skill_search, skill_load) plus everything the model explicitly
unlocked.agent.steer(...) at the agent/turn-stopping checkpoint;
forces one more step instead of letting a text-only think reply close the
turn.shared/ plugin inside a
mode directory, generated by npm run sync.The wire-level mode: every user turn opens with one think step on condition
(2) — tool definitions PRESENT in the request, tool_choice: "none" on the
wire — then a steering notice opens the execute phase on the official
provider with the resident catalog.
tool_choice is outside the harness GenerateOptions vocabulary (the
official deepseek adapter documents the mapping as an MVP cut), so reaching
this condition takes the sanctioned wire seam:
toolchoice-adapter.mjs (row 1) registers a
zero-dependency DeepSeek chat-completions adapter under its OWN provider
id (deepseek-wire-think) that puts tool_choice: "none" on the wire
whenever tool definitions are present. The official DeepSeekAdapter
cannot be wrapped (its wire body is built inside a private generator), so
this file vendors a minimal, protocol-faithful subset of the official
serialize/SSE/translate pipeline — the same assistant-message nuances
(content: "" never null, reasoning_content replayed only on
tool-call turns, tool results as role: "tool" with an (no output)
fallback) and the same usage/finish translation. Connection facts
resolve row config > llm-deepseek settings section > env, exactly like
the official row, so the same DEEPSEEK_API_KEY serves both routes.wire-think.mjs keeps the think step's assembled
catalog UNTOUCHED (that is the condition being reproduced) and swaps ONLY
the provider in the agent/request waterfall — the frozen loop-built
request and the log-reconstructability invariant are preserved. Execute
steps (and every subagent) are routed back to the captured original
provider even when the folded session header seeds them with the think
route.agent/turn-stopping steers exactly once per turn
(resume-safe from durable steering/message events), and execute steps
see the promoted RESIDENT set.Degradation ladder: if the sibling route is not registered (row removed, or
a second preset already mounted the same id — DUPLICATE_ADAPTER is caught
and warned), think steps fall back to the zero-tool condition, so a
composition mistake can never brick a session. mode: first-turn limits the
routing (and its costs) to the session's first user turn.
Costs to know before adopting: the think/execute alternation switches the
tools block of the request prefix twice per turn, so DeepSeek prefix-cache
reuse breaks from the first changed token each switch (provider id itself is
invisible to the backend cache; the tools block is what diverges). Each swap
appends a request/header change event. Set logprobs: true on the adapter
row for the opt-in research hook — the adapter requests token logprobs and
logs a per-request mean summary (the harness StreamChunk vocabulary has no
surface for logprob data, so logging is all a plugin can do today; that log
stream is exactly what offline trajectory analysis would consume).
The "make the model believe it never left Minimal" mode: the model-visible
catalog stays EXACTLY the Minimal pair (bash + str_replace_editor) for
the WHOLE session — no anchor round, no promotion, no discovery tools, no
catalog growth — while the full Standard toolset stays registered and
executes FOR REAL behind the dshx bash gateway:
dshx list # list every gateway tool
dshx web_search '{"query": "..."}' # execute the real web_search
dshx read_image '{"path": "..."}' # execute the real read_image
system-prompt/assemble keeps only the shells +
str_replace_editor on every request (think steps, post-compaction,
subagents — everything), and auto-injected context is stripped everywhere
(there is no promotion boundary to key suppression on).tools/pre-execute listener intercepts bash commands
starting with dshx, dispatches them through ctx.tools.execute() (the
full registry pipeline — policy, guards, execution, rendering), and
returns the rendered output as the command result. The deny channel is
the only sanctioned pre-dispatch way to substitute a result, so gateway
payloads arrive flagged as errors — every payload states plainly that the
tool executed and its output follows, so the model reads it as output.
The real tool really ran: the user sees genuine effects (files, searches,
subagents) exactly as if it had been called by name.dshx capability guide is appended to the system
prompt (guide: false for a byte-pure Minimal persona) so the model knows
the gateway exists without a third visible tool.The gateway refuses to dispatch the shells/str_replace_editor themselves
("invoke them directly"), which also makes recursion impossible. Unknown
tools, malformed JSON, and tool failures all come back as readable payloads.
Set gateway: false for a bare two-tool session with no interception.
The everything-is-a-plugin showcase: THREE orthogonal anchoring mechanisms
composed as independent rows, each with its own knobs, each removable or
retunable by editing one line of agent.cordis.yml. They attack the
pre-tool deliberation collapse at different moments of a turn:
| Row | Mechanism | Owns |
|---|---|---|
think-phase |
zero-tool think step + steering notice | the turn OPENING |
deliberation-gate |
depth gate denies the first tool call of a shallow turn | the FIRST ACTION |
cot-drip |
one "We …" beat after every Nth tool result (tools/post-execute additionalContexts — never blocking, never erroring) |
the LONG MIDDLE |
With mode: every-turn the think step opens every turn, the gate catches
the paths that skip it (steering continuations, resumed sessions,
straight-to-tools follow-ups), and the drip sustains deliberation across
long tool loops. Defaults are deliberately gentle (minChars: 400,
every: 4, one beat per turn); tune per workload. Swapping the
think-phase row for wire-think + toolchoice-adapter upgrades the
opening to the wire-level condition (see above) at the cost of the sibling
route and its prefix-cache churn.
Explored and rejected for this package: pure Code Mode presentation
(presentAs('code') collapses the catalog into one run_code tool) — a
single-tool surface measurably underperforms the two-tool condition in the
sibling project's evaluations; and text-only fake tools or ghost tool-call
histories — both proved unreliable anchors in practice.
All knobs are rows in each mode's agent.cordis.yml. Unknown keys fail at
preset mount.
toolchoice-adapter (in wire-think-standard/; the row must stay the first
LOCAL row):
| Key | Default | Meaning |
|---|---|---|
provider |
deepseek-wire-think |
The sibling route id the adapter owns; registering an id twice throws DUPLICATE_ADAPTER (caught, degraded). |
toolChoice |
none |
The wire tool_choice sent whenever tool definitions are present. |
baseURL / apiKeyEnv |
settings/env | Row config first, then the llm-deepseek settings section, then DEEPSEEK_BASE_URL / DEEPSEEK_API_KEY. |
logprobs |
false |
Opt-in research hook: request token logprobs and log a per-request mean summary. |
wire-think (in wire-think-standard/):
| Key | Default | Meaning |
|---|---|---|
mode |
every-turn |
every-turn opens every user turn with a wire-forbidden think step; first-turn limits it to the session's first user turn. |
provider |
deepseek-wire-think |
Must match the toolchoice-adapter row's id. |
defaultProvider |
deepseek-official |
The route execute steps restore onto. |
suppressedContextSources |
[agent-instructions, skill-catalog] |
source.kind values stripped during think steps; [] disables. |
includeSubagents |
false |
Whether subagents also think first. |
steerText |
built-in notice | The steering message that opens the execute phase. |
eternal-minimal (in eternal-minimal/; the row must stay FIRST):
| Key | Default | Meaning |
|---|---|---|
guide |
true |
Append the short dshx capability guide to the system prompt; false keeps the persona byte-pure. |
gateway |
true |
Intercept dshx shell commands and execute the real tools; false leaves the bare Minimal pair. |
gatewayCommand |
dshx |
The interception word. |
maxGatewayChars |
12000 |
Cap on one gateway result payload. |
suppressedContextSources |
[agent-instructions, skill-catalog] |
Stripped on every request (there is no promotion boundary). |
think-phase (in combo-anchored/), deliberation-gate (in
combo-anchored/), cot-drip (in combo-anchored/): see the mode
directory headers — mode / suppressedContextSources / includeSubagents
/ steerText for the split; minChars (default 400, 0 disables) /
maxGatesPerTurn (default 1) / gateText / includeSubagents for the
gate; every (default 4, 0 disables) / maxPerTurn (default 1) / text
/ includeSubagents for the drip.
wire-think-standard/ wire-level think/execute split
eternal-minimal/ Minimal pair forever + dshx bash gateway
combo-anchored/ combination package: think split + gate + drip
shared/ single source of truth for plugins used by 2+ modes
scripts/sync-modes.mjs materializes shared/ plugins into every mode dir
test/ zero-dependency test suite (npm test)
verify/ one-shot headless verification runner
Invariants, enforced by npm run check:
agent.cordis.yml rows may reference only ./local.mjs files, never ../.shared/; the copies in mode
directories are generated. Edit shared/, run npm run sync, commit both —
never edit a materialized copy.Developed and tested against:
0.1.0-rc.547f9438DeepSeek Harness is currently a developer preview and explicitly permits breaking changes. Every mode is a full snapshot of the Standard composition, so review upstream changes before using them with a newer release.
The wire mode additionally assumes the DeepSeek backend accepts the
OpenAI-style tool_choice parameter (the official adapter simply never
sends it). If the backend rejects it, the think step fails through the
normal request-error path — degrade to another mode or mode: first-turn
if that happens.
Clone this repository, then copy a mode directory into the user preset root.
Every mode installs alone; the order fields (11/9/12) keep the three from
colliding with the dsh-anchored-standard family if you install both.
Linux/macOS:
dsh_home="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$dsh_home/.agent-presets"
for m in wire-think-standard eternal-minimal combo-anchored; do
test ! -e "$dsh_home/.agent-presets/$m" && cp -R "$m" "$dsh_home/.agent-presets/$m"
done
PowerShell (one mode at a time):
$target = Join-Path $env:USERPROFILE '.dsh\.agent-presets\wire-think-standard'
if (Test-Path -LiteralPath $target) { throw "Preset already exists: $target" }
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
Copy-Item -Recurse -LiteralPath '.\wire-think-standard' -Destination $target
Fully restart DeepSeek Harness, create a blank session, and select the mode
by name. Do not switch an active session from a different preset. The wire
mode needs DEEPSEEK_API_KEY visible to the process (same key as the
official route).
Export the session JSONL and inspect request/header events:
provider: "deepseek-wire-think"
with the tool catalog present; execute-step headers show the official
provider and the resident catalog; turn/end reasons show the steered
continuation.tools array is exactly
["bash", "str_replace_editor"]; tool/call events show dshx …
commands whose results carry the real tool output.Run the local zero-dependency tests with:
npm test
For a headless one-shot check against a real harness checkout, see
verify/run-verify.mjs --help.
DeepSeek currently asks community plugin authors to publish plugins in their own
GitHub projects and add the dsh-plugin
repository topic for discovery. The official repository does not currently
accept external pull requests. See the official
CONTRIBUTING.md.
MIT. The mode compositions derive from the DeepSeek Harness Standard
preset, and shared/toolchoice-adapter.mjs adapts a subset of the official
llm-deepseek adapter pipeline; the original DeepSeek copyright and MIT
notice are retained in NOTICE.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。