dsh-web-search-ddg
aooyoo
Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no m…
PROJECT TOPICS
PROJECT README
Experimental DeepSeek Harness agent presets — one base mode plus two variants — that anchor a session's first model request on the Minimal condition (real Minimal tool schema, no auto-injected context), then promote to a small resident catalog once the session is durable, unlocking heavier Standard tools on demand.
This is a community project. It is not an official DeepSeek preset and is not affiliated with or endorsed by DeepSeek.
Welcome to submit feedback on the plugin in the form of Issues or PRs. For ideas for new plugins or useful findings, please submit them under the repository.
| Mode | Directory | First model request | Anchor mechanism | Promotion signal | Cost |
|---|---|---|---|---|---|
| Anchored Standard | preset/ |
2 tools (the Minimal pair) | Minimal tool schema | first durable tool/call or assistant/message (promoteOn: either) |
none |
| Zero-Anchored Standard | zero-anchored-standard/ |
0 tools | one fixed anchor turn | the anchor reply (assistant/message) |
+1 model call |
| Whoami Standard | whoami-standard/ |
0 tools | one "你是谁" self-introduction turn | the self-introduction reply (assistant/message) |
+1 model call |
| Eternal Minimal | eternal-minimal/ |
2 tools, forever | the visible catalog never grows; heavier tools run via the dshx bash gateway |
none (no phases) | none |
| 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, prefix-cache churn |
| 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).
injected reminders.
tool/call or assistant/message, whichever comes first.
Variants: the anchor reply.dev_tool_search, skill_search, skill_load: the
on-demand unlock surface for heavier Standard tools.shared/ plugin inside a
mode directory, generated by npm run sync.The base mode in one request lifecycle (the variants change only the first turn — see their sections):
user's first message
│
▼
┌ request #1 ─ bootstrap phase ──────────────────────────────┐
│ tools : bash + str_replace_editor (Minimal's real pair) │
│ context : no AGENTS.md digest, no skill-catalog reminder │
│ budget : adapter default (`bootstrapMaxTokens` optional) │
└─────────────────────────────────────────────────────────────┘
│ first durable tool/call OR assistant/message
▼ PROMOTION — derived from durable events, resume-safe
┌ request #2+ ─ resident phase ──────────────────────────────┐
│ tools : bootstrap pair + discovery tools + unlocked │
│ context : standard injections restored │
│ budget : adapter default (a cap is stripped on promote) │
└─────────────────────────────────────────────────────────────┘
Three first-request levers decide the trajectory (issue #11):
bootstrapMaxTokens is opt-in).DeepSeek V4 Pro conditions strongly on the API-visible tool catalog. In the Project2 evaluation, Standard and PTC produced scores of 91 and 92, while the official Minimal preset produced 99 and 96. Permanently staying on Minimal, however, gives up the Standard preset's broader tool set.
Anchored Standard separates initial trajectory selection from later tool use:
bash +
str_replace_editor, byte-identical to the official Minimal composition —
on the first model request (lever 1 above).suppressedContextSources in the
tool-bootstrap row; lever 3). User-initiated skill gestures are not
filtered, and both injections return unchanged from request #2 on.tool/call
or the first assistant/message, whichever comes first — promote to the
RESIDENT catalog: the bootstrap pair plus the discovery tools plus whatever
the model has explicitly unlocked via dev_tool_search. Dumping the full
Standard catalog at promotion pulled the trajectory back to standard-like
behavior (the post-promotion regression), so heavier tools — web_search,
subagent, workflow, … — stay one dev_tool_search call away. Requestcatalog, so a text-only first reply can no longer trap the session in
bootstrap. (promoteOn in the tool-bootstrap row selects the trigger:
either default, tool-call, or assistant-message.)
The bootstrap catalog is the same on every platform: the Minimal pair
(bash/str_replace_editor). The preset's shell is the persistent PTY bash
(the sandboxed Standard bash row is disabled — both register the bash name
into the same layer, and the tools registry rejects duplicates; Windows never
had the sandboxed bash anyway). pwsh remains available in the promoted
catalog on Windows.
Project2 V4.1b, DeepSeek V4 Pro, reasoningEffort=max, Windows native:
| Run | Ability | Reasoning blocks | we |
let's |
let me |
Visible replies |
|---|---|---|---|---|---|---|
| r1 | 98 | 193 | 179 | 88 | 1 | 1 |
| r2 | 99 | 162 | 165 | 98 | 0 | 1 |
Both runs emitted exactly two tool-catalog snapshots: the two-tool Minimal bootstrap, followed by the 25-tool Standard catalog (these runs predate the post-promotion narrowing to the resident set — see How it works). The result is reproducible evidence for this task, not a claim of universal improvement across models or workloads.
Cross-version evidence (issue #11, Windows + official endpoint, first-request
trajectory only): at the adapter-default maxTokens the Minimal tool schema
anchored 5/5 (We need modify… first lines, we 1.4, let me 0.0), while
pwsh/read, pwsh-only, and sandboxed bash/read all produced standard-like
first lines 11/11 — the tool schema, not the output cap, is the decisive
first-request variable at 256000.
Full methodology and aggregate evidence are in
xiaobright/modeltest.
All knobs are rows in each mode's agent.cordis.yml. Unknown keys fail at
preset mount.
tool-bootstrap (in preset/agent.cordis.yml; the row must stay FIRST —
waterfall registration order decides the first-request strip):
| Key | Default | Meaning |
|---|---|---|
bootstrapTools |
[bash, str_replace_editor] |
Tools visible on request #1. |
promoteOn |
either |
Promotion trigger: either, tool-call, or assistant-message. |
bootstrapMaxTokens |
unset | Optional output cap for request #1; stripped after promotion. |
suppressedContextSources |
[agent-instructions, skill-catalog] |
source.kind values stripped during bootstrap; [] disables the filter. |
compactionTools |
[] |
Extra tools available between a compaction boundary and re-promotion. |
zero-tool-bootstrap (in zero-anchored-standard/ and whoami-standard/):
suppressedContextSources and compactionTools have the same semantics
(promotion is always the first assistant/message), plus
includeSubagents — whether subagents also take the anchor phase (set true
in whoami-standard, false in zero-anchored-standard).
anchor-turn (in both variants): text — the synthetic first user message
(default "This round is a test. Tools are not open yet; all tools will open
next round." in zero-anchored, "你是谁" in whoami); includeSubagents —
whether subagents also take the anchor turn.
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). |
cot-drip (in combo-anchored/):
| Key | Default | Meaning |
|---|---|---|
every |
4 |
Attach one deliberation beat after every Nth tool result; 0 disables the drip. |
maxPerTurn |
1 |
Beats per turn. |
text |
built-in beat | The reminder text (one "We …" sentence restating the remaining goal). |
includeSubagents |
false |
Whether subagent calls are dripped too. |
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 (no StreamChunk surface exists). |
wire-think (in wire-think-standard/): same mode / suppressedContextSources /
includeSubagents / steerText semantics as think-phase, plus
provider (must match the toolchoice-adapter row's id) and defaultProvider
(the route execute steps restore onto, default deepseek-official).
instruction-hint (all modes): promoteOn matching the mode's promotion
semantics (either in the base mode, assistant-message in the variants) —
the one-shot "instruction files exist, read them before acting" hint waits
for promotion.
preset/ Anchored Standard — the base mode
zero-anchored-standard/ variant: fixed zero-tool anchor turn
whoami-standard/ variant: "你是谁" anchor turn, subagents inherit
eternal-minimal/ variant: Minimal pair forever + dshx bash gateway
wire-think-standard/ variant: wire-level condition (tools + tool_choice=none)
combo-anchored/ combination package: think split + gate + drip rows
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.tool-bootstrap row stays the FIRST row of preset/agent.cordis.yml.This repository deliberately ships no AGENTS.md/CLAUDE.md: the presets' whole mechanism is a clean request #1, stripping exactly those instruction-file digests from it (issue #6: 0/9 anchored with the injection present). Shipping one would only feed later rounds and contradict the mechanism being documented. Everything an assistant needs is in this README.
Developed and tested against:
0.1.0-rc.547f9438On the 0.1.0-rc.5 source checkout, bootstrapMaxTokens reaches the actual
first request (the first request/header records the cap, adapterDefaults
stays empty), because llm.prepareCall only materializes a default maxTokens
when the proposed config has none. One prebuilt profile package observed in
issue #11 (CLI launcher reporting 0.1.0-rc.6) overwrote the proposed cap
with adapterDefaults.maxTokens; there the cap is a no-op. The default
composition therefore relies on the Minimal tool schema alone (which anchors
at the adapter default with no cap) and leaves bootstrapMaxTokens as an
opt-in for standard-schema bootstraps.
DeepSeek Harness is currently a developer preview and explicitly permits breaking changes. This preset is a full snapshot of the Standard composition, so review upstream changes before using it with a newer release.
Clone this repository, then copy the entire preset directory into the user
preset root under the id anchored-standard. Every mode directory in this
repository is self-contained: the zero-anchored-standard/,
whoami-standard/, eternal-minimal/, wire-think-standard/, and
combo-anchored/ variants install the same way, alone or together, with no
other directory required (see their sections below).
PowerShell:
$target = Join-Path $env:USERPROFILE '.dsh\.agent-presets\anchored-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 '.\preset' -Destination $target
Linux/macOS:
dsh_home="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$dsh_home/.agent-presets"
test ! -e "$dsh_home/.agent-presets/anchored-standard"
cp -R preset "$dsh_home/.agent-presets/anchored-standard"
Fully restart DeepSeek Harness, create a blank session, and select Anchored Standard (experimental). Do not switch an active session from a different preset.
Export the session JSONL and inspect request/header events. Reproduction
checklist (issue #11 asks for the first two explicitly, because both are the
variables that decide the anchor):
config.maxTokens value: with bootstrapMaxTokens unset
(the default), the first header records the adapter default (e.g. 256000
with adapterDefaults.maxTokens: true); with a cap configured it records
the cap (e.g. 1024 with no maxTokens adapterDefault).tools array must
be exactly ["bash", "str_replace_editor"] — the official Minimal preset's
real schemas, not Standard's pwsh/read.dev_tool_search/skill_search/skill_load plus any tools the model
already unlocked;dev_tool_search unlocks) and restore the standard context
injections.Run the local zero-dependency tests with:
npm test
promoteOn: either, the session promotes after its first
durable tool/call OR its first assistant/message, whichever comes first —
request #1 sees the bootstrap catalog and every later request sees the
resident catalog. A text-only first reply therefore still promotes at
request #2; set promoteOn: tool-call to restore the original behavior,
where a first response that makes no tool call never promotes.tool/call already exists.bootstrapMaxTokens is
opt-in. When set, the first request is capped and the cap is explicitly
stripped after promotion (the next request's seed proposal carries the
previous header's maxTokens forward).dev_tool_search —
not the full Standard dump. The Standard sandboxed bash row stays disabled
in favor of the persistent shell (same tool name, same layer; see Why). When
unlocked, the read/write/edit tools keep the sandboxed filesystem while
str_replace_editor uses the preset's local fs.promoteOn values fail at preset mount instead.source.kind is listed in suppressedContextSources (default:
agent-instructions and skill-catalog, the two automatic injections
Standard adds over Minimal). Set the list to [] to disable the context
filter; add other source.kind values to suppress more. A filter failure
degrades to keeping every message rather than eating context.dev_tool_search
unlocks a new tool; request-prefix cache continuity breaks at those points.An extra test mode that does not change the Anchored Standard logic above. It uses the same Minimal-aligned system prompt, but instead of exposing two tools on the first request it injects one fixed zero-tool anchor turn:
anchor-turn plugin prepends a
fixed user message — "This round is a test. Tools are not open yet; all
tools will open next round." — ahead of it.Anchoring on the first message — not on session creation — keeps the blank-session preset switcher usable. Subagents always see the resident catalog.
Measured behavior (opencode-go, DeepSeek V4 Pro, reasoningEffort=max): the
anchor request is stable "we"-style with zero let me; the following
tool-bearing requests return to the "The user wants…/Let me" style. This mode
is a comparison point for whether the zero-tool first turn is worth the extra
model call — not a claim that tool rounds stay "we"-style.
Install as a separate preset id:
dsh_home="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$dsh_home/.agent-presets"
test ! -e "$dsh_home/.agent-presets/zero-anchored-standard"
cp -R zero-anchored-standard "$dsh_home/.agent-presets/zero-anchored-standard"
Restart DeepSeek Harness, create a blank session, select Zero-Anchored Standard (experimental), then send your first message.
A usability-oriented variant of the zero-tool anchor idea: the first turn is a natural self-introduction prompt instead of a fixed test message, and the user's real first message is deferred to the next turn. Whatever the user types first, the session warms up exactly one round and everything is ready when the real message is processed:
anchor-turn plugin prepends a
fixed user message — "你是谁" (who are you) — ahead of it in the next-turn
inbox queue.next-turn message per turn, so the first model
request sees only the anchor on an EMPTY tool surface and replies with a
self-introduction; that reply is the promotion signal.str_replace_editor, the discovery tools) already
unlocked — heavier Standard tools are one dev_tool_search away.The anchor text is configurable via the anchor-turn row's text option
(default "你是谁"). Anchoring on the first message — not session creation —
keeps the blank-session preset switcher usable.
Whoami Standard ships with includeSubagents: true on both the
zero-tool-bootstrap and anchor-turn rows, so subagents spawned from a
session inherit the same anchor flow as top-level sessions:
str_replace_editor, and the discovery tools).Set includeSubagents: false on both rows to restore the plain behavior,
where subagents start with the resident catalog immediately. Each subagent
costs one extra model call for its anchor turn — a delegation-heavy session
pays it per subagent.
zero-anchored-standard keeps subagents plain by default; enabling the same
flow there means setting includeSubagents: true on its zero-tool-bootstrap
and anchor-turn rows (its anchor text stays the fixed test notice).
The trade-off of the mode itself is one extra model call per session: the anchor turn is always taken, even when the first message is urgent.
The directory is self-contained; install it alone or alongside any other mode.
Install as a separate preset id:
dsh_home="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$dsh_home/.agent-presets"
test ! -e "$dsh_home/.agent-presets/whoami-standard"
cp -R whoami-standard "$dsh_home/.agent-presets/whoami-standard"
Restart DeepSeek Harness, create a blank session, select Whoami Standard (experimental), then send your first message — the self-introduction round runs first, and your message is answered with the full tooling on the next turn.
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.
Install as a separate preset id:
dsh_home="${DSH_HOME:-$HOME/.dsh}"
mkdir -p "$dsh_home/.agent-presets"
test ! -e "$dsh_home/.agent-presets/eternal-minimal"
cp -R eternal-minimal "$dsh_home/.agent-presets/eternal-minimal"
Restart DeepSeek Harness, create a blank session, select Eternal Minimal
(experimental), then work as usual — the model composes shell commands,
and dshx … lines run the heavier Standard tools for real.
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.
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 and does not mandate a community repository
template. See the official
CONTRIBUTING.md.
MIT. preset/agent.cordis.yml is derived from the DeepSeek Harness Standard
preset; the original DeepSeek copyright and MIT notice are retained in
NOTICE.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。