Skip to main content
This page lists the exact formats and limits for Firewall. To set up a policy, see Guard agent tool calls with Firewall.

Policy fields

You manage saved policies in app.ngrok.ai under Firewall, or with the Firewall Policies API. Each field shows its dashboard label first, then its name in the plugins field. The API uses the same names, except that it spells on_error as onError and puts every rule in one rules list, where each rule sets its tier to hardDeny, softDeny, or allow.

Rule fields

Each rule type takes only its own match field. For example, a regex rule with instructions is rejected.

Matching details

  • Tool names match the whole name and are case-sensitive. * matches any characters, so mcp__github__* matches mcp__github__create_issue.
  • Regex patterns are case-sensitive unless they start with (?i). Against a tool call, the pattern matches the tool name, a space, and the raw JSON arguments. Block rules also match the arguments with JSON escapes decoded.
  • Regex rules on request parts match all the text of each part, across every message, joined with newlines.
  • In a Responses request, instructions and prompt.variables count as messages, call items as assistant turns, and *_call_output items as tool results. Tool definitions include tools that a tool search or an MCP tool list added to the conversation.
  • In a Gemini request, systemInstruction and the contents parts count as messages, functionResponse parts as tool results, and functionDeclarations as tool definitions. Images, audio, and video have no text to read. Firewall can’t read a PDF or other file part, so On error decides for rules that read the part.
  • Decision rules on request parts read the system and developer messages plus the newest input: the latest user message and any tool results it carries. They read up to about 41 KB of text. When the text is longer, the Ngrok-AIG-Firewall-Request header reports a partial read.

The plugins field

Add a plugins array to a /v1/chat/completions, /v1/responses, /v1/messages, or Gemini generateContent request body to check that request with extra rules. The gateway removes the field before it sends the request to the provider.
The rules in plugins run on top of the saved policies that apply to the key, as described in How policies combine. A request can add up to 48 rules, and a rule can’t reuse the ID of a rule in a saved policy. The policy editor in the dashboard shows a ready-to-copy plugins field for the policy you’re editing, under Try it in one request.

What a blocked caller gets

A block returns HTTP 200, so agents keep running and the model can react. In Dry run, nothing is blocked, but the same results appear in the header and safeguard_results.

Blocked request

When a request rule blocks a request, the gateway doesn’t send it to the model. The response holds one assistant message with this text, in the response format of the endpoint you called:
rule lists the names of the rules that blocked the request. Each name is in brackets, with a space between names. When Firewall couldn’t check the request and On error is Block, rule is empty and the text says the request couldn’t be checked.

Blocked tool call

When a response rule blocks a tool call, the gateway removes the call and adds this text to the assistant message. In a Responses request, an assistant message item with this text takes the call’s place in output. In a Gemini request, a text part with this text takes the call’s place and keeps the call’s thoughtSignature:
rule names only rules from enforced policies. When Firewall couldn’t check the call and On error is Block, rule is empty and the text says the call couldn’t be evaluated. If no tool calls remain, the response ends as if the model had finished:
  • Chat Completions: finish_reason changes to stop.
  • Messages: stop_reason changes from tool_use to end_turn.

safeguard_results

Responses carry a top-level safeguard_results array when Firewall checked something. In a streamed response, it’s in the final chunk for Chat Completions, in the message_delta event for Messages, in the response object of the final event, such as response.completed, for Responses, and in the chunk with a finishReason for Gemini. Request rules report one entry per rule:
Tool call checks report one entry per tool call ID:
A Gemini function call often has no ID. Its entry then uses the call’s position in the response, such as candidates[0].parts[1]. A response with no tool calls carries no dangerous_tool_use entry.

Response headers

The header lists rule IDs, while the blocked message and safeguard_results show rule names. The dashboard sets each ID from the rule’s name when you create the rule. Tool call results have no header, because the gateway may already be streaming the response. Read safeguard_results for them.

Errors

A single check that can’t run, such as a decision model timeout, doesn’t return an error. With Block set, it blocks the request or tool call with the 200 responses described in What a blocked caller gets.