ReasonBlocks evaluates trajectory health with six trajectory monitors that run server-side on POST /monitors/evaluate. task_profile selects which weight preset the server applies; the weighted sum of the monitor scores is the composite that drives steering injection.
These weights live in rb-api, not the SDK. The SDK forwards your task_profile (and any monitor_weights override) to the server, which owns the resolution. There is no local monitor suite to weight on the client.
The six monitors
Each monitor returns a score in [0, 1] where 1 is maximum badness. A monitor “fires” when its individual score crosses the fire threshold; the weighted sum across all six is the composite.
| Monitor | What it detects |
|---|
claim_contradiction | The agent’s stated conclusions contradict each other or earlier findings. The only detector that examines what the agent concluded, not what it called. |
semantic_loop | The same action or search repeated with reworded inputs (embedding-based, so “session timeout” / “session expiry” / “session token expiration” count as one loop). |
verification_skip | The agent reaches a conclusion without verifying its work (no test run, no re-read of the changed file). |
cyclic_compression | Repeated re-summarization / context churn — the agent compresses and re-derives the same state in cycles. |
late_sprawl | The trajectory sprawls late: new tools and tangents introduced deep into a run that should be converging. |
silent_topic_drift | The agent quietly drifts off the original task without acknowledging the change. |
Built-in profiles
Three profiles are defined in rb-api/app/scoring/monitors.py (WEIGHTS_BY_PROFILE). Select one with task_profile:
from reasonblocks import ReasonBlocks
rb = ReasonBlocks(
api_key="rb_live_...",
task_profile="coding", # or "pr_review", "qa"
)
coding (default)
Standard weights for an agent that edits code, runs tests, and may loop. claim_contradiction leads.
| Monitor | Weight |
|---|
claim_contradiction | 0.30 |
semantic_loop | 0.25 |
verification_skip | 0.15 |
cyclic_compression | 0.10 |
late_sprawl | 0.10 |
silent_topic_drift | 0.10 |
pr_review
Read-only review agent. semantic_loop leads — review agents most often fail by re-explaining the same diff — and cyclic_compression / late_sprawl are raised for runs that sprawl across files.
| Monitor | Weight |
|---|
claim_contradiction | 0.20 |
semantic_loop | 0.30 |
verification_skip | 0.10 |
cyclic_compression | 0.15 |
late_sprawl | 0.15 |
silent_topic_drift | 0.10 |
QA / tutoring agent. claim_contradiction and silent_topic_drift dominate (wrong or off-topic answers are the primary failure mode); verification and compression matter less.
| Monitor | Weight |
|---|
claim_contradiction | 0.40 |
semantic_loop | 0.15 |
verification_skip | 0.05 |
cyclic_compression | 0.05 |
late_sprawl | 0.10 |
silent_topic_drift | 0.25 |
Resolution order on the server: defaults ← named profile preset ← per-call monitor_weights overrides. Unknown monitor names in overrides are dropped; negative weights are clamped to 0; each weight is capped at 1.0.
Per-call weight overrides
Pass monitor_weights on ReasonBlocksConfig to override individual weights on top of the chosen profile. The override is forwarded into MonitorSteeringInjection and rides on every POST /monitors/evaluate request.
from reasonblocks import ReasonBlocksConfig
config = ReasonBlocksConfig(
monitor_task_profile="coding",
monitor_weights={
"semantic_loop": 0.40, # raise — catch loops sooner
"verification_skip": 0.05, # lower — your agent verifies elsewhere
},
)
Partial dicts are fine — unspecified monitors fall through to the profile, then to server defaults.
monitor_weights is only a field on ReasonBlocksConfig. The simpler ReasonBlocks(...) constructor doesn’t expose it — use the config + build_middleware path when you need per-call weight overrides.
Custom profiles
You can create and manage named profiles per organization through the dashboard or the REST API (GET/POST /v1/monitor/profiles). A custom profile referenced by task_profile resolves the same way as a built-in. The set of valid monitor names is returned by GET /v1/monitor/scorers.