Skip to main content
When the FSM is in FAST state, the middleware skips E1, E2, and E3 retrieval entirely. This is by design — FAST means the agent is sailing through easy steps and the pattern-store query overhead isn’t worth paying. Monitor scoring still runs so loop detection stays active.The middleware records this on the step entry as:
Inspect it across a run:
To stay out of FAST longer, raise fast_threshold or grow fast_window:
step_log is the primary debugging surface. Every model call becomes one StepLogEntry with the full intervention details:
Walk through these in order:1. e_traces_enabled=FalseDisables the entire E1/E2/E3 retrieval pipeline. The default is True.2. FSM is in FASTAll E-tracing skips when the FSM is in FAST. Inspect entry.fsm_state and entry.skipped_reason across step_log.3. E1 monitor gate deniesE1 retrieval is gated by monitor health — it only runs when at least one monitor fired in the current call, the composite score is above 0.15, or a monitor fired in either of the previous two calls. By design, E1 stays quiet when the run looks healthy. Check entry.monitors_fired over the trailing window.4. Per-injection capsE1 caps at one retrieval per run (max_calls=1). E2 caps at one. E3 fires only on step 0. Monitor steering caps at 5 injection events per run with cooldowns: 2 steps in SLOW/SKIP, 3 in NORMAL, 5 in FAST.5. Silent API failureFailures inside before_model and wrap_model_call are caught and logged at WARNING. Set the SDK logger to DEBUG to see them:
6. Empty pattern scopeA new account or organization may have no E1 patterns yet. E2 and E3 will still fire. Check entry.injection_sources to see which tiers contributed.
TokenSavingMiddleware must come last. It runs after ReasonBlocksMiddleware and GeneralMonitorMiddleware so it compresses whatever they injected before the LLM call goes out.
When you use rb.middleware() or build_middleware(), the ordering is handled for you. Manual ordering only matters when constructing middleware classes directly.
Putting TokenSavingMiddleware before ReasonBlocksMiddleware means it processes history before any injection is added — silent correctness failure, not an error.
All exceptions inside before_model and wrap_model_call are caught, logged at WARNING, and swallowed. The agent continues — it just receives no injection on that step. Live telemetry events are fire-and-forget; if the endpoint is unreachable, events are dropped after a timeout and the agent loop is never blocked waiting for them.Watch for log lines like:
A degraded run typically shows up as step_log entries with empty injection_sources while fsm_state is NORMAL or SLOW.
Mostly. Set e_traces_enabled=False and live_streaming_enabled=False:
With this configuration, the FSM, scoring, and local pieces of the middleware run without any network calls. Note that monitor steering still requires a server call (POST /monitors/evaluate) when constructed; if you also need monitors-off, configure ReasonBlocksConfig with enable_monitor_steering=False and use build_middleware.
Yes. Pass base_url:
base_url is forwarded to every internal client (E-trace retrieval, monitor evaluation, live telemetry).
Pass a metadata dict to rb.middleware() (or rb.openai_hooks()):
The metadata dict is stored as JSON on the run record and is queryable from the dashboard’s run filter. Use it for any tag that doesn’t fit a named field. Values can be strings, numbers, or booleans.
Both are multi-tenant scoping fields on the run record.
  • org_id identifies the organization. When you use a per-customer rb_live_* key bound to a specific org, the API overrides this with the key’s authoritative org regardless of what you pass.
  • project_id is a finer-grained grouping inside the org — separate infra-review from frontend-review agents within the same customer.
Both default to "default". For SaaS deployments, set org_id to your customer identifier and project_id to the workload name.