dsh-advisor
English | 中文
Independent-model advisory review for DeepSeek Harness.
After each tool step, a separate reviewer model audits the agent's most recent
operations. When it finds a real concern (destructive or irreversible
operations, contract/schema violations, deviations from the user's explicit
request, correctness bugs), it injects a short [advisor] guidance message
into the next model call so the agent can self-correct. When the work is
sound, nothing is injected and the review costs only the (cheap) reviewer
call.
dsh has no built-in advisor; this plugin implements one on the standard
agent/pre-step waterfall (the same injection channel used by
dsh-agent-instructions and dsh-compaction-basic).
Install
dsh plugin add @slhssb/dsh-advisor
or add to the profile's package.json:
"dependencies": { "@slhssb/dsh-advisor": "^0.1.0" },
"dsh": { "profile": { "bundles": ["@slhssb/dsh-advisor"] } }
Then npm install (or pnpm install) in the profile directory and restart dsh.
Configuration
Defaults target the DeepSeek official API (deepseek-official provider) with
the cheap deepseek-v4-flash model. The API key is not handled by this
plugin: the deepseek-official adapter resolves it per request from the
DEEPSEEK_API_KEY environment variable or the credentials store.
The defaults need no override — they already target the DeepSeek official
API (deepseek-official/deepseek-v4-flash). To point the reviewer
elsewhere, override in the profile's cordis.patch.yml (last write per row
wins). This example routes the reviewer through a third-party relay: the API
key is resolved by that provider's adapter (here the TOKENRHYTHM_API_KEY
environment variable, per its apiKeyEnv in settings.yaml) — this file
never holds keys:
- id: advisor
config:
provider: tokenrhythm
model: deepseek-v4-pro
maxTokens: 512
maxHistoryMessages: 40
interval: 1
timeoutMs: 30000
| Key | Default | Meaning |
|---|---|---|
provider |
deepseek-official |
Reviewer provider route (any OpenAI-compatible adapter works). |
model |
deepseek-v4-flash |
Reviewer model. |
maxTokens |
512 |
Reviewer output cap. |
maxHistoryMessages |
40 |
Most recent derived messages sent to the reviewer. |
interval |
1 |
Review every N steps that contain tool results (1 = every step). |
timeoutMs |
30000 |
Per-review timeout; a timeout degrades silently. |
Disable entirely with disabled: true on the row, or set an empty
provider/model to fall back to the current request route (agent/session
request header, then agent options).
Rules (deterministic checks)
Beyond the LLM review, rules give you zero-cost, deterministic checks that
match the latest tool call (tool name + raw arguments JSON) against regular
expressions. They never fail and never cost a token; a warn rule injects a
[advisor] Rule check: message into the next step, a block rule rejects
the step outright (opt-in — default is warn).
- id: advisor
config:
provider: deepseek-official
rules:
- id: no-recursive-delete
pattern: 'Remove-Item|rm\s+(-rf|-r\s*-f)|del\s+/[sq]'
message: '检测到破坏性删除命令,请确认目标路径与用户授权。'
action: warn # or block
tools: ['pwsh', 'bash'] # optional: only run for these tool names
enabled: true # optional, default true
| Key | Default | Meaning |
|---|---|---|
id |
— | Stable rule id (logged when the rule fires). |
pattern |
— | Case-insensitive JS regex matched against toolName + arguments. |
message |
— | Text injected as [advisor] Rule check: …. |
action |
warn |
warn injects guidance; block rejects the step. |
tools |
all | Optional tool-name substrings the rule applies to. |
enabled |
true |
Disable without removing the rule. |
Invalid rules (missing fields, bad regex) are skipped with a warning; the
agent flow is never blocked by a misconfigured rule. Multiple warn hits are
merged into one message. block fires before the LLM review — the review is
not run for a blocked step.
How it works
agent/pre-step(waterfall) fires before every model call.- The plugin scans the session log for the newest
tool/resultevent. If none exists, or its seq was already reviewed, the step passes through. - Otherwise the reviewer model receives the recent derived history plus the review instruction and streams a response.
- A non-empty response is wrapped as a
usermessage (source: { kind: 'plugin', plugin: 'dsh-advisor' }, text prefixed[advisor]) and spliced into the step's messages after the claimed messages, before system context — the same insertion pointdsh-agent-instructionsuses, so the next model call is guaranteed to see it. - Review failure (LLM error, timeout, empty output) logs a warning, injects nothing, and advances the reviewed-seq marker so the same batch is not retried on the next step. The agent's main flow is never blocked.
Injected [advisor] messages are ordinary user/message log entries; they
never produce tool/result events, so review can never recurse on itself.
Development
npm install
npx tsc -p tsconfig.json
node test/smoke.mjs # hand-built fakes; no network
lib/ is committed so git-installed consumers work without a build step;
node_modules/, test/smoke.mjs, and package-lock.json are gitignored.
npm pack ships lib via the files whitelist.
Publish
Published on npm as @slhssb/dsh-advisor; the repository carries the GitHub
dsh-plugin topic for discovery. Bump version in package.json, publish,
then tag the release:
npm publish --access public
git tag v0.1.0 && git push --tags
No comments yet. Be the first to write one.