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-tools and @deepseek-ai/dsh-llm are 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:

  1. 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.

  2. On every tools/post-execute, match the result’s text block (optionally including the success canonical value in JSON) against applicable rules. Rules with when: success remain 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.

  3. When the action of a hit rule is error, the listener returns { kind: 'block' }. The registry converts this into an isError result: 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.

  4. Only when a rule with action: context is hit does the listener pass through, and it appends a UserMessage notification to the decision’s additionalContexts. The source is { kind: 'plugin', plugin: 'loud-failure', form: 'notice', summary }, which the Web UI displays as a collapsed line.

  5. If there is no hit, next() passes through. Rules with action: off never 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: rules is configurable, and action supports three outcomes: error, context, off.

Pre-use notes:

  1. Version coupling. Requires DeepSeek Harness 0.1.0-rc.6 and Node.js 20+, the plugin is only tested on this version.

  2. 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.

  3. 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.