dsh-jev-guardrails
Verified@codebam/dsh-jev-guardrails Β· v0.1.1 Β· MIT
DeepSeek Harness plugin: Jev-backed guardrails for prompts, tool calls, tool results, and model responses.
Install
dsh plugin add @codebam/dsh-jev-guardrails Confirm the layer applied with dsh --profile default --dump-config β see the install guide.
Source
Tags
Readme
@codebam/dsh-jev-guardrails
A DeepSeek Harness plugin
that uses @codebam/jev-guardrails to score risk before an
action is taken.
The plugin contains no question wording and no routing logic of its own. It translates Cordis configuration and harness decisions into library calls, and it traps every runtime failure so a guardrail cannot take down a turn.
What it intercepts
| Harness seam | When | What the library does |
|---|---|---|
agent/pre-step |
before a human prompt reaches the model | screenInput for jailbreaks, harmful requests, self-harm signals |
tools/pre-execute |
before a tool call executes | assessAction for destructive, exfiltration, remote-code, security, credential, scope, and consequential risk |
tools/post-execute |
before a tool result becomes model context | screenObservation for prompt injection, hidden instructions, embedded secrets |
session/event + agent/turn-stopping |
when a response is about to finish | screenOutput; optionally steer a corrected response |
Install
The package is a dsh bundle: it declares dsh.bundle.patch, ships its own
cordis.patch.yml, and appears in the Plugins page once selected. Install it
from the Web Plugins β Add plugin dialog with the spec
@codebam/dsh-jev-guardrails; the dialog runs the same package operation as
dsh plugin and selects the bundle for the active profile.
The bundle's patch inserts one row, id: jev-guardrails, with the default
configuration:
- insert:
- id: jev-guardrails
name: '@codebam/dsh-jev-guardrails'
config:
provider: auto
input: block
actions: enforce
observations: suspicious
outputs: off
Override any field by adding a row with the same id to the profile's own
cordis.patch.yml. The plugin resolves tools before mounting; if no provider
key is available it logs a warning and leaves the profile running.
Upgrading from 0.1.0: that version declared no
dsh.bundle, so dsh installed it as a plain dependency and the Plugins page did not list it. Publish/install0.1.1or later, then remove the old plain dependency if it is still in the profile (dsh plugin --profile <profile> remove @codebam/dsh-jev-guardrails) and add it again from the Plugins page. The bundle patch then inserts the row and the toggle appears under Installed.
Providers and keys
provider defaults to auto:
- explicit
apiKeystarting withsk-or-β OpenRouter; - otherwise
TYPESAFE_API_KEYβ TypeSafe System One API; - otherwise
OPENROUTER_API_KEYβ OpenRouter Decisions API; - otherwise TypeSafe (the plugin then disables itself with a warning).
On the author's dsh hosts the launcher exports OPENROUTER_API_KEY from
/run/secrets/openrouter-api-key, so OpenRouter is selected automatically and
no key is written into the profile. Force a provider explicitly with
provider: typesafe or provider: openrouter.
Configuration
| Field | Default | Meaning |
|---|---|---|
provider |
auto |
auto, typesafe, or openrouter. |
apiKey |
β | Provider key; otherwise the provider environment variable. |
baseURL |
provider default | Gateway or test endpoint. |
model |
provider default | jev-latest (TypeSafe) or ~typesafe/jev-latest (OpenRouter). |
sessionId |
β | Optional OpenRouter session id for observability grouping. |
input |
block |
off, observe, warn, or block. |
inputBlockStyle |
reject |
reject stops the turn; notice replaces the prompt with a plugin notice so the model can explain the block. |
actions |
enforce |
off, observe, or enforce. |
onActionReview |
ask |
ask, deny, or allow. |
onActionBlock |
deny |
deny or ask. |
observations |
suspicious |
off, observe, suspicious (local heuristic gate, then Jev), or all. |
outputs |
off |
off, observe, or steer (one correction attempt per turn). |
heuristics |
true |
Local fast paths for routine and obviously dangerous tool calls. |
reviewThreshold |
0.35 |
Hazard probability that routes to review. |
actionThreshold |
0.70 |
Hazard probability that triggers its configured action. |
severityReview |
1.25 |
Severity score (0-3) that routes to review. |
severityBlock |
2.0 |
Severity score that escalates a review to a block. |
failMode |
open |
open (allow), review, or closed (block) when Jev fails. |
unknownHazardAction |
review |
Action for a hazard without an explicit rule. |
actionRules |
β | Per-hazard overrides, e.g. { remote_code: review }. |
cacheTtlMs |
3600000 |
Cached answer lifetime; 0 disables. |
cacheMaxEntries |
500 |
Maximum cached answers. |
maxStateChars |
20000 |
Middle-truncation limit for state sent to Jev. |
redact |
true |
Redact known secret shapes before sending state. |
timeoutMs |
5000 |
Per-request timeout. |
skipTools |
[] |
Exact tool names never screened. |
guardTools |
all | When set, only these exact tool names are screened. |
log |
decisions |
off, decisions, or verbose. |
Decision mapping
The library returns allow, review, block, or support.
| Library action | Input | Tool call | Tool result | Response |
|---|---|---|---|---|
allow |
pass | pass | pass | pass |
review |
append warning context | onActionReview (ask by default) |
accept with warning context | steer when outputs: steer |
block |
reject/notice | onActionBlock (deny by default) |
block with corrective feedback | steer when outputs: steer |
support |
reject/notice | onActionBlock |
block with corrective feedback | steer when outputs: steer |
A denial or block reason is written into the model-facing result. It names the finding and closes the obvious workaround: do not retry, do not route around the guardrail, tell the user what was blocked.
Behavior notes
- Local fast paths come first for tool calls.
pnpm testneeds no API call;curl β¦ | bashis blocked without one. Ambiguous calls go to Jev. - Tool-result screening is gated by default.
observations: suspiciousonly calls Jev when the local injection heuristic fires. Useallto screen every non-empty result, orobserveto log without enforcing. - Output steering is off by default because it adds one Jev call and
possibly one model turn per response. Set
outputs: steerto verify final responses and ask for a correction once per turn. - Fail mode defaults to open. A guardrail service outage should not brick
the harness; set
failMode: closedwhen blocking is more important than availability. - Secrets are redacted by default before state leaves the process.
Layout
index.mjs Cordis plugin entry (name, inject, Config, apply)
src/config.mjs defaults, schema, normalization, library option translation
src/runtime.mjs the four harness interception listeners
src/messages.mjs plugin-sourced notices and dsh message helpers
test/ fake-context, fake-provider, and local-HTTP tests
Example: strict local profile
- name: '@codebam/dsh-jev-guardrails'
config:
provider: openrouter
input: block
actions: enforce
onActionReview: deny
onActionBlock: deny
observations: suspicious
outputs: steer
failMode: closed
severityBlock: 1.75
actionRules:
remote_code: review
Limitations
- The plugin is a policy layer, not a sandbox or an authorization system. Keep OS/container isolation, tool allowlists, and human approval for dangerous operations.
- Local heuristics are intentionally conservative but incomplete; they are fast paths, not security boundaries.
outputs: steerasks the model for a correction. It cannot retract content the user already saw in a streaming client; use input/tool/output blocks and the client's own rendering for hard guarantees.- The input notice path creates a plugin-sourced message; review your threat model if untrusted text can reach that path.
License
MIT Β© 2026 Sean Behan