Gateway
Steering
Corrective controls that preserve workflow continuity by hardening risky requests and responses before the gateway blocks.
Steering is the gateway’s set of corrective controls around guard and policy decisions. It can neutralize suspicious context before a provider call, constrain a risky attempt, sanitize or remove a tool call, retry a withheld response, or route a blocked attempt to another configured model. In Enforce, the gateway blocks when the effective guard results still require a block after the eligible controls and attempt budget are exhausted.
For a long-running agent, successful pre-provider steering preserves the active workflow instead of returning an HTTP 403 that the client must recover from. Chat keeps the safe remainder of the existing message history, while Responses keeps previous_response_id, conversation, or replayed input items. The steered request uses the current provider attempt, avoiding a separate restart request and preserving any context-reuse or prompt-caching opportunity supported by the upstream provider. Recovery stays in-band, avoiding a user-visible workflow reset.
The continuation still runs a normal provider inference. Exact context reuse, latency, token accounting, and billing are provider-dependent. Steering avoids application-level workflow reconstruction; it does not promise free model execution.
The classifiers detect risk. Steering applies the corrections enabled in runtime policy. The project’s enforcement mode decides whether supported mutations run or are only evaluated.
Steering runs in the OpenAI-compatible gateway. Direct SDK and REST checks return classifier results to your code and do not apply gateway corrections. See INT-Input, INT-Tooling, and INT-Output.
The full sequence below applies to non-streaming requests and buffered streaming. Incremental streaming uses checkpoint and hold-back semantics because released bytes cannot be recalled. See Streaming.
Where steering sits#
On a buffered request, the runtime follows this order:
- The custom blocklist and INT-Input inspect the latest user request. Recent tool results may also run through tool-result quarantine.
- Context splicing, prompt armoring, and sampling constriction prepare the provider request when their triggers match. In Observe, these changes are computed on a copy and the original request is sent upstream.
- After a successful provider response, enabled INT-Tooling, INT-Output, and INT-CoT checks run. INT-CoT remains advisory unless its conjunction escalates an already-flagged tool or output result.
- In Enforce, tool policy can sanitize or remove tool calls. Eligible unsafe tool or output results can start an informed retry. A configured model escalation can run after the retry path no longer applies.
- Each new provider response is screened again. The last effective results determine whether the gateway returns the response or an HTTP
403policy block.
Two decisions are intentionally terminal. A custom-blocklist match cannot be remediated by context splicing. A per-tool block action is not stripped or retried.
Corrective controls#
| Control | Surface | Runtime behavior |
|---|---|---|
| Tool-result quarantine | Inbound Chat tool messages | Screens recent tool results and replaces unsafe content before the provider call. |
| Context splicing | Chat history and latest Responses input | Neutralizes trusted localized spans, withholds an affected tool result, or quarantines an unsafe turn when prior workflow context exists. |
| Prompt armoring | Chat and Responses provider request | Prepends a defensive Chat system message or Responses instructions on elevated-risk calls and retries. |
| Sampling constriction | Provider request | Tightens caller-supplied sampling and token limits on elevated-risk attempts. |
| Argument sanitization | Tool calls | Applies configured key, path, domain, prefix, and length rules before a tool call is returned. |
| Tool-call pruning | Chat tool calls | Removes unsafe or denied tool calls when the response still has safe content or tool calls to return. |
| Informed retry | Buffered provider call | Withholds an unsafe result and re-attempts with the policy reasons, fresh armor, and constriction. |
| Model escalation | Buffered provider call | Routes a blocked attempt to a configured attack-class model or fallback model. |
Most guardrail controls are enabled by default. Model escalation is off by default. INT-Output and INT-CoT are also off by default, so their response-side paths do not run until you enable those classifiers.
Context splicing#
Context splicing examines recent Chat messages and the latest Responses input, excluding system and developer messages. Localized classifier evidence can remove a specific unsafe span. Deterministic instruction-hijacking patterns can harden flagged latest input and recent non-system Chat history, but they do not by themselves downgrade an unsafe latest-input verdict to safe. For user and assistant messages, eligible matching spans are replaced. An affected Chat tool result is withheld as a whole because its remaining content is not treated as independently trusted.
If classifier-localized removal changes an unsafe latest user message and leaves an actionable task, the runtime records the original verdict and treats the remediated input as safe for the pre-provider decision. It does not make a second INT-Input call. When an unsafe verdict has no trusted localized span, or localized removal leaves no meaningful task, the runtime can quarantine the entire latest turn and substitute a safe continuation bridge only when prior workflow context is present. The bridge instructs the model to continue from prior non-suspicious context when possible and otherwise ask the user to restate only the legitimate task. Without prior workflow context, Enforce blocks before the provider call.
Chat Completions treats another user, assistant, or tool message as prior workflow context. Responses accepts a replayed user or assistant message item, previous_response_id, or conversation; typed non-message items such as function_call_output are not screened and do not establish workflow context. The upstream provider remains responsible for validating an external reference. Responses hardens replayed user and assistant message items like Chat history, and tool-result quarantine does not yet parse Responses input items. A custom-blocklist match remains terminal on both endpoints, and turning context splicing off restores pre-provider blocking for unsafe input in Enforce.
Retry and escalation#
Informed retries are controlled by tool_interception and output_gating. Unsafe results retry by default when the control is enabled. Flagged results retry only when the corresponding retry_on_flagged setting is on. A retry creates a new provider response, so the enabled tool, output, and INT-CoT checks run again.
Tool retries append a sanitized record of the denied tool call and a policy denial result, then ask the model to continue without executing it. This retry shape is available on Chat Completions only. Output retries work on buffered Chat Completions and Responses requests. Model escalation can then replace the request model with an attack-class mapping or fallback model when the current decision is still a block and budget remains.
A material, rising INT-CoT conjunction can promote an already-flagged tool or output result to unsafe. That effective result enters the same retry, escalation, and block path. INT-CoT cannot initiate a correction by itself.
Tool-call steering#
Tool interception combines deterministic policy with INT-Tooling. Per-tool rules can allow, block, sanitize arguments, or request a retry without the tool. Argument rules can allow or remove paths, redact values, restrict URL domains and path prefixes, and truncate strings. In Enforce, successful sanitization changes the tool arguments before the response reaches the client. A requested sanitization that cannot be applied completely fails closed.
On Chat Completions, unsafe or retry_without_tool calls can be removed while safe calls or assistant content remain. If pruning would leave no useful response, the request can enter the informed-retry path. Responses API argument sanitization is supported, but tool-call pruning and tool-interception retries are not.
Effective results#
The decision reducer uses the guard results after any correction available on that path:
| Effective state | Decision |
|---|---|
unsafe | Block. In Enforce, eligible retries or model escalation run before the final HTTP 403. |
error | Allow when fail_open is on; block when it is off, unless another unsafe result already requires a block. |
flagged | Allow and record observed risk unless a configured flagged-result retry or INT-CoT conjunction changes the path. |
safe | Allow. |
A corrected allow is visible in the trace. The final decision breakdown can retain fields such as original_verdict and remediated_by, alongside the effective result used for the outcome.
Attempt budget#
global_max_attempts caps total provider calls per request from 1 to 5, with a default of 3. The original call, informed retries, and model escalations share that budget. Tool retries have a separate 0 to 3 cap (default 1), output retries have a separate 0 to 3 cap (default 2), and model escalation has a separate 0 to 2 cap (default 1 while the control itself is disabled).
Controls that only rewrite an existing request or response do not consume an attempt. If no provider attempt remains and the last effective decision is a block, Enforce returns the policy block without another call. A pre-provider splice, including continuation-bridge substitution, uses the original provider attempt rather than adding a retry.
Steering in Observe#
Observe evaluates pre-provider mutations on a copy, records their mutation mode as simulated, and sends the original request upstream. The gateway still runs the enabled guards on the provider result and records the policy decision, but it returns the original provider result instead of applying a policy block.
Response mutations, informed retries, and model-escalation calls run only in Enforce. Observe does not fabricate a re-screen result for a provider call it never made. Use the simulated pre-provider action cards, guard results, and final decision to tune policy before enabling mutations and blocks.
Traces#
Applied or evaluated controls produce trace metadata and, when the runtime records that action, guardrail spans such as guardrail.tool_result_quarantine, guardrail.context_splicing, guardrail.prompt_armoring, guardrail.sampling_constriction, guardrail.tool_interception, guardrail.informed_retry, and guardrail.model_escalation. An active INT-CoT conjunction emits guardrail.cot_integrity_conjunction.
Span records include status, decision action, reason codes, and latency_ms. Retry and escalation spans also carry attempt indices and the relevant bounded state. The trace detail presents spans on the timeline. Recorded pre-provider controls, tool interception, retries, and escalation also appear as action cards.
Stored request, response, metadata, and span attributes follow the project’s content mode. metadata_only retains decisions, timings, counts, and redacted attributes without raw request or response content. Trace delivery is asynchronous and best-effort, so it does not block the request path.
Configuration#
Steering controls live under detector_config.proxy_runtime.guardrails. The policy screen writes this structure. This example uses the runtime defaults for the bounded controls and leaves model escalation off:
{
"detector_config": {
"proxy_runtime": {
"guardrails": {
"global_max_attempts": 3,
"prompt_armoring": { "enabled": true },
"context_splicing": { "enabled": true, "max_messages": 24 },
"tool_result_quarantine": {
"enabled": true,
"retry_on_flagged": false,
"max_recent_tool_messages": 24
},
"tool_interception": {
"enabled": true,
"retry_on_flagged": false,
"max_retries": 1,
"default_action": "allow"
},
"output_gating": {
"enabled": true,
"retry_on_flagged": false,
"max_retries": 2
},
"sampling_constriction": {
"enabled": true,
"temperature": 0.0,
"top_p": 0.5,
"max_tokens_cap": 1024,
"enforce_max_tokens_when_absent": false
},
"model_escalation": {
"enabled": false,
"max_escalations": 1,
"fallback_model": null,
"attack_class_models": {}
}
}
}
}
}Sampling constriction only lowers explicitly supplied temperature and top_p values. Token fields are capped when present. Set enforce_max_tokens_when_absent to impose the configured cap when the caller did not supply a token limit. Per-tool argument rules are documented under Policy controls.
What steering is not#
- Not detection. Classifier results, deterministic context patterns, and tool policy rules trigger corrective controls; steering does not replace those signals.
- Not authorization. Network policy and least-privilege identity still bound what the agent can reach. See The two planes.
- Not a rewrite of intent. Context splicing preserves an actionable user task when one can be isolated. The continuation bridge continues the established workflow or asks the user to restate the task; it does not invent a replacement objective.
- Not an independent INT-CoT action. INT-CoT can affect this path only by escalating an already-flagged tool or output result through its conjunction.