# How OpenRouter Armor screens tool calls, and when the client must stop them
> OpenRouter Armor classifies proposed tool calls against developer rules. Responses and Chat Completions can withhold flagged calls; Messages compatibility leaves the client responsible.
By BIG CHANGE Editorial
Published: 2026-10-17T01:51:13.522Z
Updated: 2026-10-17T01:51:13.522Z
Canonical: https://bigchange.ai/blog/openrouter-armor-tool-call-screening-client-enforcement

AI-generated conceptual illustration by BIG CHANGE; no actual OpenRouter interface or tested security result is depicted.
OpenRouter's [Armor beta](https://openrouter.ai/docs/guides/features/plugins/armor) puts a rule classifier between a model's proposed tool call and the application that might execute it. For an agent developer, the critical detail is where a verdict actually stops execution. On Chat Completions and Responses, Armor can withhold a flagged call. In the Messages API's Claude Code compatibility mode, the flagged `tool_use` remains in the response, and the client must decline to run it.
The current documentation describes a beta available since October 2026. BIG CHANGE reviewed the documented request and response contracts on October 17. We did not send an API request, run an agent or measure its security performance.
## The big change
- **What changed:** An OpenRouter agent can send its proposed tool calls through a classifier that applies developer-written rules before the calls reach the application. A flagged call is skipped in the default enforce path, with a reason returned so the model can continue.
- **Why it matters:** Developers can express action-level limits in prose, including exceptions for narrowly permitted work. The Messages compatibility contract still gives the client the decisive execution step: a client that ignores a flagged verdict can run the call anyway.
- **What to watch:** Teams need to match their client to the chosen API output mode, test rules against their own traffic and decide how classifier errors should behave. The beta's formats may change, and OpenRouter says the classifier can both block acceptable calls and miss unacceptable ones.
## Follow a call from proposal to verdict
For each proposed tool call, OpenRouter says it holds the call before forwarding it to the application. Its decision model receives the call, the rules and the conversation so far, estimates whether each rule matches, and combines those results into `flagged` or `not_flagged`. An unflagged call is released unchanged. In enforce mode, a flagged call is marked to skip execution; the model receives the reason and can attempt a narrower call or explain the denial. This is a classifier judgment about the proposed action, not proof that a later tool or the whole agent is safe.
The rule tiers answer different questions. A `hard_deny` match blocks regardless of an allow rule or the user's request. A `soft_deny` match can be cleared by an `allow` match or by the user asking for that exact operation on that exact target in the conversation. An `allow` rule never blocks a call on its own. OpenRouter also documents a built-in soft-deny for a boundary the user has set and not lifted. Developers supply facts, such as a trusted repository or deploy target, in `environment`; stale facts can make a rule less precise. Named rule objects expose an ID and name in verdicts. Optional thresholds default to 0.6 for deny rules and 0.7 for allow rules.
The [documented Responses example](https://openrouter.ai/docs/guides/features/plugins/armor#example) gives a `bash` tool a hard-deny rule for `git push`. With `output_mode: "custom_item"`, a flagged push is replaced by an `openrouter:armor_blocked` item containing the call and reason, followed by the model's response. The example shows what the docs say the service returns; it is not a test conducted by BIG CHANGE.
## Choose the output contract before executing tools
For Chat Completions and Responses, the default `text` mode removes a blocked call and puts an `<openrouter_armor_blocked>` marker in assistant text. The Responses API also supports `custom_item`, which returns the typed blocked item where a `function_call` would have appeared. The docs say to echo that item unchanged in the next Responses input and not to create a separate `function_call_output` for it. `safeguard_results` records verdicts by call ID.
The Messages API has a materially different default when the request carries `safeguards`: `claude_code_compatibility` leaves the flagged `tool_use` in `content[]` and adds its `flagged` result to `safeguard_results`. **The application must read that result and refuse to execute the call.** OpenRouter explicitly warns that a Messages client ignoring the verdict will run a flagged tool use. A developer who cannot control the client can request `output_mode: "text"` on Messages so OpenRouter withholds the call. Asking an API for an output mode it cannot carry returns a 400.
Claude Code auto mode through OpenRouter's Ori metaharness uses the Messages contract without an extra Armor plugin entry. The docs say Claude Code declines flagged calls, writes an error result into the transcript and lets the model continue. They also say an Anthropic endpoint supporting its classifier can supply a passed-through verdict; Armor evaluates on other endpoints. That is the documented integration behavior, not a claim that every third-party client implements it correctly.
## Configure and check a narrow rule set
For a custom agent, the [Armor guide](https://openrouter.ai/docs/guides/features/plugins/armor#example) places an `armor` entry in `plugins`, with versioned `classifier_context` (`v: 1`), `auto_mode` rules and optional environment facts. Start with the action and protected resource the rule should recognize, then choose hard deny for a prohibition that should survive user consent or soft deny when exact consent or a named allowance can legitimately clear it. The docs advise describing the action rather than one command spelling and keeping environment facts current.
The default `enforce` mode acts on verdicts. `audit` reports the same verdicts while releasing every call, including flagged ones. It is a way to inspect real traffic and adjust rules before enforcing, not a protective mode. Audit cannot be combined with `claude_code_compatibility`. In either mode, read `safeguard_results`: `not_flagged` means permitted, `flagged` identifies a matched rule, `unavailable` means evaluation failed, and `skipped` identifies an unevaluated provider-native tool. When streaming, the verdict object arrives at the end of the response, so a client using Messages must wait for it before acting on a tool use.
OpenRouter lists `on_error: "block"` as the default when the classifier times out, errors or cannot handle an oversized request; `on_error: "log"` releases the call. In Claude Code compatibility mode, an `unavailable` call is released with the verdict visible. Provider-native server tools are skipped by default unless `evaluate_native_tools` forces them out of the native path for evaluation. These settings and the actual tool path belong in a team's integration check; an Armor entry alone does not show that every tool was evaluated.
## The beta's cost, speed and coverage limits
OpenRouter reports that evaluation added **279 milliseconds at the median and 334 milliseconds at the 90th percentile** with its Claude Code compatible rule set loaded. Those are vendor-reported measurements under that stated condition, not a benchmark of a particular agent or every rule set. Each call is evaluated once before release or block. Evaluation is not billed during beta; OpenRouter says it will announce pricing before general availability. The docs do not establish a future rate.
The decision model can produce false positives and misses because it judges prose rules against prose arguments. The docs recommend using audit verdicts on actual traffic and tuning individual rule thresholds. Armor evaluation is not yet supported for HIPAA, Zero Data Retention or data-region-restricted requests. A plugin-armed request in one of those contexts gets a 403; a Claude Code request instead releases the call as `unavailable`, and Claude Code falls back to local auto-mode evaluation. The beta warning also covers changes to configuration fields, `safeguard_results` and the `openrouter:armor_blocked` item type.
Armor screens proposed calls at the model-to-application handoff. That makes it a different mechanism from [Microsoft's MXC command containment](https://bigchange.ai/blog/mxc-agent-command-containment-guide) and [NVIDIA's OpenShell and Sentry runtime controls](https://bigchange.ai/blog/nvidia-open-agent-safety-platform-agent-controls), which place enforcement around a workload or its access. For Armor, the immediate implementation decision is whether the chosen response format withholds a flagged call or requires the client to stop it.
## Sources & further reading
- [OpenRouter Armor documentation](https://openrouter.ai/docs/guides/features/plugins/armor), accessed October 17, 2026. Primary source for beta status, classifier sequence, rule precedence, API response contracts, error behavior, privacy-context exclusions, reported latency and beta billing. These are OpenRouter's documented claims; BIG CHANGE did not run the plugin.
- [BIG CHANGE on Microsoft MXC](https://bigchange.ai/blog/mxc-agent-command-containment-guide) explains policy-based containment for agent-generated commands. It describes a separate enforcement layer, not an earlier phase of Armor.
- [BIG CHANGE on NVIDIA OpenShell and Sentry](https://bigchange.ai/blog/nvidia-open-agent-safety-platform-agent-controls) describes software access controls and an optional hardware monitoring design. It is related context, not a direct continuation of this OpenRouter feature.
## Sources
- [OpenRouter Armor documentation](https://openrouter.ai/docs/guides/features/plugins/armor) — Primary product documentation checked October 17, 2026. Establishes beta status, classifier and rule behavior, API response shapes, errors, restricted contexts, reported latency and beta billing. Vendor claims, not an independent test.
- [BIG CHANGE: How to set an MXC policy for agent-generated commands](https://bigchange.ai/blog/mxc-agent-command-containment-guide) — Prior coverage of separate command containment mechanism; used only for relationship context.
- [BIG CHANGE: NVIDIA's agent safety platform](https://bigchange.ai/blog/nvidia-open-agent-safety-platform-agent-controls) — Prior coverage of separate runtime access controls and optional monitoring design; used only for relationship context.
The BIG CHANGE newsletter
The big picture. At your pace.
Recent stories on AI and robotics, the shifts worth watching and practical ideas to use. Choose a daily briefing, weekly digest or monthly perspective.
Next scheduled send (UTC): . Your first edition arrives at the next scheduled send after you confirm.
Your privacy, your choice.
Necessary storage supports site security and remembers your choices. Optional Google Analytics stays off until you allow it. You can read every story with necessary storage only. Privacy details