Preface¶
For those running agents, you have likely encountered this type of failure: a tool call exits with code 0, and the output looks normal, so the model proceeds based on that. Only a few steps later do you piece together the truth from various signs—the initial call actually failed. pandoc prints a warning about a missing glyph but still writes the PDF; a Python traceback is swallowed by the pipe, with the exit code provided by tail; a ; chain mixes command not found in with a bunch of normal output. The exit code says success, the model reads success, and the error propagates downstream.
Of course, you can find the cause by digging through session logs later, but a better time is right when the failure happens. The DSH philosophy is “everything is a plugin,” and the tool execution chain has extension points like tools/post-execute. The dsh-plugin-loud-failure introduced in this article hooks into this point: it matches warning signatures before the result reaches the model, making silent failures explicit.
What is this¶
dsh-plugin-loud-failure is a DeepSeek Harness plugin maintained by Rhymer-Lcy, under the MIT license. In a nutshell: a tools/post-execute strategy that matches warning signatures within successful tool outputs; upon a hit, it blocks that result or attaches a notification. It does not modify any tools or the loop.
Versions and dependencies are fully specified:
- Plugin version 0.1.1;
- Requires DeepSeek Harness 0.1.0-rc.6 (where
@deepseek-ai/dsh-toolsand@deepseek-ai/dsh-llmare fixed at 0.1.0-rc.6); - Node.js 20+.
The author notes that this is the only tested version, and peer ranges are fixed based on the release. After upgrading the harness, pay attention to whether the plugin has followed suit with the release.
How it works¶
The core is a waterfall listener registered at tools/post-execute, working in the following order:
-
On load, merge built-in rules with the user-configured
rules(user rules with the same id as built-in rules replace them in place), and compile all regexes. If the rules table is invalid—illegal regex, duplicate ids, stateful flags, empty message—it will reject the plugin load with the offending rule id. Bad configuration fails at startup, rather than waiting for the first tool call. -
On every
tools/post-execute, match the result’s text block (optionally including the success canonical value in JSON) against applicable rules. Rules withwhen: successremain quiet on outputs that already carry a failure marker: non-zero[exit code: N]lines, non-zero exit code[status: ...]trailers,[sandbox: file access denied ...]. The model would see these anyway, so they don’t count as silent failures. -
When the
actionof a hit rule iserror, the listener returns{ kind: 'block' }. The registry converts this into anisErrorresult: the content starts with an explanatory header, and the original output is preserved as-is; the canonical value ceases to exist, and Code Mode programs cannot consume the polluted value. -
Only when a rule with
action: contextis hit does the listener pass through, and it appends a UserMessage notification to the decision’sadditionalContexts. The source is{ kind: 'plugin', plugin: 'loud-failure', form: 'notice', summary }, which the Web UI displays as a collapsed line. -
If there is no hit,
next()passes through. Rules withaction: offnever run.
The listener is registered via ctx.on and unloads with the plugin; configuration changes reload the plugin and register a new listener.
Silent Failures Covered by Built-in Rules¶
The built-in rules table consists entirely of failures observed in practice that were hiding behind successful exit codes:
| Observed Call | Model Sees | What Actually Happened |
|---|---|---|
pandoc ... --pdf-engine=xelatex prints Missing character: There is no ₂ in font ... |
PDF written, exit code 0 | The subscript for SpO₂ was silently dropped from the PDF |
python script.py \| tail -n 20 |
Last 20 lines, exit code 0 | The traceback has scrolled past, exit status provided by tail |
pandocc in.md -o out.pdf; ls -l out.pdf |
bash: pandocc: command not found plus a list, exit code 0 |
Nothing was built, exit status provided by ls |
python calc.py prints RuntimeWarning: invalid value encountered in divide |
An array, exit code 0 | The array contains nan |
PowerShell 5.1 command with 2>&1 |
NativeCommandError, $? is false |
The program actually exited 0, but stderr was wrapped by PowerShell |
Windows console prints ��� |
Text, exit code 0 | GBK/UTF-8 code page mismatch, text corrupted |
If these scenarios are common in your workflow, the built-in rules work out of the box; upon a hit, you either get an isError result or see a notification in the next round of requests.
Installation and Enablement¶
Below are three ways, from simple to complex.
Installing from release tarball¶
No build step, no build authorization needed, command is:
dsh plugin --profile web add https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure/releases/download/v0.1.1/dsh-plugin-loud-failure-0.1.1.tgz
After installation, confirm the plugin layer appears in the config:
dsh --profile web --dump-config
In the output, you should be able to see a # == dsh-plugin-loud-failure layer.
Additionally, the dsh plugin add printing peer dependency warnings for @deepseek-ai/* is expected: the profile resolves these packages from the harness installation, rather than installing them next to the plugin.
Installing from GitHub fixed commit¶
dsh plugin --profile web add github:Rhymer-Lcy/dsh-plugin-loud-failure#<commit-sha>
Git installation pulls the source code; pnpm needs to be allowed to run the package’s prepare script (content is tsc). The first add will fail and print the full key that needs to be allowed; append it to the profile’s pnpm-workspace.yaml and retry:
# $DSH_HOME/profiles/web/pnpm-workspace.yaml (copy key from pnpm's hint)
allowBuilds:
"dsh-plugin-loud-failure@https://codeload.github.com/Rhymer-Lcy/dsh-plugin-loud-failure/tar.gz/<commit-sha>": true
Running directly from source code checkout¶
First, build:
git clone https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure.git
cd dsh-plugin-loud-failure && pnpm install && pnpm run build
Then insert a line into overlay.yml, pointing to lib/index.js:
# overlay.yml
- insert:
- id: loud-failure
name: /absolute/path/to/dsh-plugin-loud-failure/lib/index.js
dsh web --patch ./overlay.yml
Uninstalling¶
dsh plugin --profile web remove dsh-plugin-loud-failure
Configuration¶
After installation, the bundle inserts a line with id: loud-failure and default schema values. There are two verified configuration keys:
rules: An array of user rules, defaults to empty. User rules with the same id as built-in rules replace them in place; new ids are appended in order; two user rules with the same id will cause a load failure.shellTools: Specifies tools to be checked, defaults to[bash, pwsh, job_output].
There is a common pitfall when overriding configuration: patch replaces the entire line of config. If you are overriding the loud-failure configuration in your profile’s cordis.patch.yml, you must restate all keys you want to keep.
Use Cases and Considerations¶
Who is it for:
- People with heavy shell-like tool calls in their workflow who have been bitten by silent failures; the six scenarios above are covered by built-in rules.
- People who want to crystallize their team’s own warning signatures into rules:
rulesis configurable, andactionsupports three outcomes:error,context,off.
Pre-use notes:
-
Version coupling. Requires DeepSeek Harness 0.1.0-rc.6 and Node.js 20+, the plugin is only tested on this version.
-
Git install authorization matters. Allowing the prepare script means the repository code will run outside any agent sandbox during installation; be sure to fix the commit. Release tarball installation does not have this step.
-
Permissions. The plugin runs with the permissions of the current dsh process; check source code and license before installing any third-party plugin. This plugin is MIT licensed, and source code is publicly available on GitHub.
Conclusion¶
This plugin’s approach is quite restrained: it doesn’t change tools or the loop; only at the tools/post-execute stage, it transforms warning signatures behind exit code 0 into an isError result the model cannot ignore, or a visible notification. For those running long chains of tool calls, it changes “discovering it a few steps later” to “seeing it right now.”
- GitHub Repository: https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure
- Community Directory Page: https://www.skillhub.cn/plugins/Rhymer-Lcy/dsh-plugin-loud-failure
The directory is an independent community site and has no official affiliation with DeepSeek or Synthflow.