Guides › Tune to your risk tolerance
Tune to your risk tolerance
Doberman ships with sane defaults, but nothing about how loud it is is fixed. This page covers the dials: strictness mode, the enforcement dial, the opt-in default role, the subjective preference weights, friction telemetry, and message tone.
On this page
- Strictness modes, doberman mode
- Enforce, monitor, or off, doberman enforcement
- The built-in default role, doberman role enable-default
- Subjective preference weights, doberman prefs
- Friction telemetry and gated tuning, doberman tune
- Approval memory (5 minutes)
- Plain or technical wording, doberman message-tone
- Recovery actions
Strictness modes, doberman mode#
Set a mode in .doberman/policies.yaml or with doberman mode <mode>. Every mode change made this
way (the CLI or the setup wizard) is recorded in the append-only policy-change ledger, viewable with
doberman policy-history. Lowering strictness (paranoid to strict to balanced to light) is a
weaken and requires confirmation plus a possession factor: TOTP if enrolled, otherwise the local
Doberman password. With neither enrolled, the lowering fails closed; confirmation alone never
suffices. Raising stays frictionless and applies immediately:
| Mode | Best for | Bulk-delete threshold | Step-up for unknown destinations | Step-up for behavioral anomalies | Lethal-trifecta exfil |
|---|---|---|---|---|---|
| Light | Exploratory / trusted environments | 100 files | No | No | AUTH |
| Balanced (default) | Everyday coding agents | 25 files | No | Yes | AUTH |
| Strict | Production repos, shared codebases | 10 files | Yes | Yes | BLOCK |
| Paranoid | Highly autonomous or security-critical agents | 3 files | Yes | Yes | BLOCK |
Hard blocks (secret exfiltration, destructive commands, role-boundary violations, smuggled-token-channel exfiltration) are identical in every mode. The mode dial only changes where step-up authentication is required for ambiguous or high-risk actions.
A few mode-dependent behaviors worth knowing:
- CI/CD pipeline configuration (GitHub Actions, GitLab CI, Jenkins, CircleCI, Azure Pipelines) steps up to authentication in every mode: that config builds, tests, signs, and deploys the repo, so an agent rewrite is always a human-in-the-loop moment.
- Default-registry package fetches get a Light/Balanced relaxation: a recognized package-manager
fetch with no explicit URL (
pip install requests,npm install,poetry install,go mod download, and similar) passes without a prompt, because its route is the manager's default registry, a stronger signal than the unknown hosts those two modes already allow. Anything that could redirect the route, an explicit URL,--index-url/--registry, a proxy or registry environment variable, a chained command, or the publish/upload direction, still steps up in every mode.git pull/git fetchalso still step up, since their route depends on the configured remote. Strict/Paranoid keep the prompt for every package fetch. - Unknown network destinations step up to authentication only in Strict/Paranoid; Light and Balanced treat a plain unknown host as allowed (a secret leaving to any host is still a hard block in every mode, and sharper destination smells, embedded credentials, raw IPs, unresolvable hosts, still step up everywhere).
- Checksum-valid personal or financial data (a payment card number, an IBAN, a dashed US SSN) bound for an external destination steps up to authentication in every mode, but only when the data co-occurs with an outbound destination, not merely written locally. Only the class label ("payment card number") ever reaches a log, never the value.
- The lethal trifecta (sensitive data, untrusted-content provenance, and an external destination
together) steps up to authentication in Light/Balanced and is a hard
BLOCKin Strict/Paranoid, at both decision layers, so a step-up on some other signal can never mask it back down. - A local hard smuggled-token channel is a hard
BLOCKin Strict/Paranoid and stays AUTH in Light/Balanced.
Enforce, monitor, or off, doberman enforcement#
Orthogonal to strictness mode is the enforcement dial (enforce (default) / monitor / off),
which decides whether Doberman acts on a verdict or only observes:
enforce: the normal behavior, AUTH prompts and BLOCK denies.monitor: the discretionary layer (behavioral anomalies, soft step-ups) is evaluated and recorded (doberman log/doberman tuishow what would have happened) but never blocks or prompts. Use it to try Doberman on a repo without friction, or to tune before turning it on.off: the discretionary layer isn't evaluated at all.
Set it with doberman enforcement <enforce|monitor|off>; no argument prints the current state.
Turning the dial down is gated the same way as lowering mode: confirmation plus the strongest
enrolled possession factor, recorded in the ledger; with neither factor enrolled the change fails
closed. Turning it back up re-arms automatically, no gate.
The objective floor stays live in every state. Secret exfiltration, destructive commands, protected-path
writes, role/policy blocks, and the lethal trifecta always block regardless of the dial; monitor/off
only softens the discretionary verdicts. The on-disk value is ledger-verified on every call, so a
hand-edited enforcement: off in policies.yaml with no matching approved change is caught and
clamped back to enforce.
The built-in default role, doberman role enable-default#
The role boundary is normally dormant until you hand-write .doberman/role.yaml; with no active role
the role rule abstains. doberman role enable-default opts a repo into a packaged, generic
least-privilege role for a coding assistant instead, no YAML required: ordinary source, config, docs,
and test files anywhere in the repo classify as in-scope, while CI/CD config, infra/**,
migrations/**, and any unrecognized file type step up to authentication. Paths outside the repo
root are always a hard block, for every role. An explicit .doberman/role.yaml always takes
precedence over the opt-in default. Turning the opt-in off (doberman role disable-default) is a
weaken, gated behind the same possession-factor confirmation as lowering mode or enforcement.
Subjective preference weights, doberman prefs#
The adaptive layer's four "care" weights, confidentiality, reversibility,
interruption_tolerance, and blast_radius, each in [0, 1], tune how readily discretionary
behavioral signals step up. The objective hard-block floor never moves. Show the active vector with
doberman prefs, set one weight with doberman prefs <dimension> <value>. The same lowering rule as
mode applies: lowering a weight requires TOTP if enrolled, otherwise the local Doberman password,
with neither it fails closed. Raising a weight is a strengthen and always applies immediately. Every
attempt, approved or denied, is recorded in the append-only ledger.
Friction telemetry and gated tuning, doberman tune#
Every AUTH prompt is already in the redacted decision log; doberman tune turns it into a friction
report: interventions per session, top AUTH reasons, approval rates by reason and by target class,
and a weekly trend. Where an (action_type, target_path_class) pair has been approved every single
time, at least --min-occurrences times (default 5), and every one of those AUTHs was a
role_out_of_scope prompt (never a secret/exfiltration/destructive/control-plane code, that
allowlist is fixed), it proposes a standing elevation: a narrow, time-limited, revocable PASS for
that exact class. doberman tune never applies anything by itself, running it only reports.
Accepting one with doberman tune --accept <id> routes through the same possession-factor-gated
weaken chokepoint as any other policy loosening, and the resulting grant is revocable early with
doberman revoke <elevation-id>.
Approval memory (5 minutes)#
After a human completes a real local_auth or two_factor proof, Doberman remembers only a keyed
HMAC fingerprint of that exact action for 300 seconds. An identical repeat still prompts; it uses
soft_confirm and says how many minutes ago the exact action was approved. A soft-confirm approval
never extends or chains the window. The decision, risk, and reason codes do not change, and the
decision log records soft_confirm+memory distinctly.
Identity includes action type, tool name, unredacted command or structured arguments, canonical target paths, and repo root. The raw values are HMAC input only and are never retained. Host hooks also require matching session ids when both sides have one; the raw MCP proxy has no session id and uses repo scope, as do entries where either side lacks a session id. Missing fingerprint keys, storage errors, missing repo roots, and tainted sessions all fall back to the full tier.
Memory never reduces authentication for file deletion, critical risk, role-boundary violations, encoded exfiltration, opaque commands, protected paths, destructive or history-rewriting commands, bulk operations, irreversible high-blast actions, or correlated destructive flows. Role elevation keeps its own narrow, time-limited, single-use grant and never participates.
Use doberman approvals status, doberman approvals clear, or
doberman approvals ttl <seconds>. The allowed TTL is 0–900 seconds; 0 disables all reads and
writes. Raising the TTL, including enabling from 0, is a weakening and requires the existing
possession-factor gate. Lowering, disabling, and clearing are strengthenings and are ungated.
Plain or technical wording, doberman message-tone#
The authorization prompt speaks plain English by default, for example "Your agent wants to run a
command: git push --force main. The command looked destructive. Approve this exact action?", so
you can read a catch and decide in seconds without parsing reason codes. Prefer the detailed
engineering view? doberman message-tone technical switches to the terse [RISK: …] role: … reason:
… block, and doberman message-tone human switches back. It changes wording only: cosmetic, not
possession-factor gated, and it never touches the decision, the reason codes, or what lands in the
decision log.
Recovery actions#
Taint clearing, tool-pin approval, learned-memory reset and pruning, and fully removing a project all live in the recovery guide.
Every gated change above is also recorded as a policy version (pv1: + a content hash) in
.doberman/policies.db; doberman policy-versions lists them and --verify confirms the policy on
disk is the last recorded one. See POLICY_VERSIONS.md ↗.