Response-style profiles¶
Response-style profiles give per-role control over worker output verbosity. A reviewer role can run terse while an investigator role runs verbose, without hand-editing role prompt templates. The style is resolved deterministically at spawn time and rendered into the worker's system prompt as an addendum.
Source:
src/bernstein/core/agents/response_style.py- resolution + renderingsrc/bernstein/core/agents/spawner_core.py- spawn-time wiringsrc/bernstein/core/config/config_schema.py-response_stylefield
The three styles¶
| Style | Maps to mode profile | Effect |
|---|---|---|
terse | fast | Compresses prose; shortest worker output. |
balanced | smart | Neutral house style (the default). |
verbose | deep | Fuller narration and reasoning in prose. |
balanced is the neutral default and renders an empty addendum, so a spawn with no declared profile is byte-identical to a pre-feature spawn. Only terse and verbose inject an addendum.
The addendum body is the mode-profile preamble from templates/mode_profiles/{fast,smart,deep}.yaml. No new prompt dialect is introduced; the vocabulary reuses the existing conciseness scale.
Style carve-outs¶
The style applies to prose only. Every non-empty addendum carries a fixed carve-out block instructing the worker never to compress, truncate, or restyle code blocks, commit messages, error text, or completion-contract JSON payloads. Those are always reproduced in full.
Configuring it¶
Declare response_style per role under role_model_policy in your seed config (bernstein.yaml). The special default entry sets the fallback for roles that do not declare their own:
role_model_policy:
default:
response_style: balanced # seed-level fallback
reviewer:
cli: claude
model: sonnet
response_style: terse # reviewers run terse
investigator:
cli: claude
model: opus
response_style: verbose # investigators run verbose
The value is validated against the closed vocabulary (verbose / balanced / terse) at parse time. A style whose mapped template file is missing raises a typed ResponseStyleTemplateError during config validation - not at spawn time - so a dangling template reference fails fast.
Resolution order¶
The style for a given spawn is resolved in this fixed order; the first source that supplies a valid style wins:
Task.metadata['mode']- accepts a style name (verbose/balanced/terse) or the equivalent mode-profile name (fast/smart/deep).- The role's own
role_model_policy.<role>.response_style. - The seed default
role_model_policy.default.response_style. - The built-in default,
balanced.
Unknown values fall through to the next source rather than raising, so a stale Task.metadata['mode'] value cannot block a spawn. Config-level typos are rejected earlier by the seed parser.
The same inputs always resolve to the same style and the same rendered addendum, so the resolution is snapshot-testable and reproducible across machines.
Identity, ledger, and audit¶
When a profile is explicitly declared (anything other than the built-in default), the SHA-256 of the rendered addendum is:
- folded into the task identity used by the deterministic schedule projection, and
- stamped onto the task's cost-ledger entry (
response_profileplusprofile_content_sha256) and audit trail.
That stamping is what makes per-profile cost attribution possible - see Per-profile cost attribution. A spawn that falls through to the built-in balanced default is not folded into identity, keeping unset-profile runs byte-identical to before.