Skip to main content
Policies are evaluated at three stages: session (connection time), request (before query execution), and response (after data retrieval). Each stage provides different input data for making policy decisions.
For available enforcement actions at each stage, see Enforcement. If you have existing policies using pre_request / post_request, see Legacy Stage Names.

Policy Scope

By default, policies apply universally to all users, resources, and data locations. You can narrow the scope within each policy using conditions.

User Context Quick Reference

Access user information via input.user and input.end_user:

Resource Context Quick Reference

Filter by resource via input.resource:

Policy stages

Session stage

Available inputs

Available actions

For this policy stage, these actions are possible: For SSH and Kubernetes exec sessions, Formal re-evaluates session rules while the session runs, for example when a session monitor triggers. See Enforcement for each action’s parameters.

Request stage

Request rules are evaluated by the proxy when it intercepts a request (query) just before sending it to the resource. This evaluation stage is especially useful in blocking write requests.

Available inputs

Available actions

For this policy stage, four types of actions are possible: allow, block, rewrite, and decrypt.

Response stage

Response rules are evaluated by the proxy when it intercepts data received from the resource. This evaluation stage is particularly useful in the context of masking or filtering read requests.

Available inputs

Available actions

For this policy stage, these actions are possible: allow, block, filter, mask, encrypt, and rewrite. rewrite at this stage changes HTTP response headers or bodies.

Standard input data

Policies can access various data types, including user information, resource information, SQL query information, and HTTP request information. The following sections describe the available data types.

Session object

Request object

Application object

Client network object

User object

Connector object

Resource object

Column object

input.row lists all columns extracted from your SQL query. A single returned column can come from multiple source columns (e.g. when using wildcards, joins, or unions), and thus result in several policy columns. When the Connector cannot resolve a source, the returned column itself stands in as its own policy column. This column lineage mapping is then used by the Connector’s policy engine: a response rule that masks a policy column will be able to mask every returned column whose lineage includes it. For example, in SELECT email FROM users UNION SELECT email FROM customers, the returned email column has two source columns: users.email and customers.email. Either one alone is enough to mask it for the entire result.

Function object

Function categories are used to group functions into different categories. The following categories are available: aggregate, bitwise, conditional, context, conversion, data_generation, date_time, differential_privacy, encryption, file, geospatial, hash, metadata, notification, numeric, scalar, semi_structured, string_and_binary, system, table, vector_similarity, window. These categories are inspired by the Snowflake documentation.

Space object

HTTP object

Native users

You can enforce policies on the Native User selected for an upstream connection. input.native_user contains the selected label. This policy allows only the reader label:

Native user assignment

The native_user_assignment field explains how Formal selected the Native User: See Legacy Native Users for the legacy selection behavior behind these values. This policy blocks every explicit override:

Requested and assigned Native Users

Native Users add input.native_user_selection. It can contain:
requested is present when the client uses an @<label> suffix. assigned is present when the Resource has a default Native User selection. The selected Native User is requested when both values exist. Policies can compare the two before allowing the connection:
The user_type value describes the credential shape. See supported credential types for the full list. See Select a default Native User for selection examples.

ClickHouse resources

ClickHouse request policies receive ClickHouse-specific fields under input.clickhouse. HTTP transport context is available through input.http at request and response policy. SQL context is available through input.sql_query. Database and write-target context use input.db_name and input.table_paths.

ClickHouse object

For database, query, and table-path inputs, see ClickHouse policy evaluation.

Snowflake resources

You can enforce policies on Snowflake resources based on the role used to connect to the resource.

Snowflake object

MongoDB resources

MongoDB request policies receive the command being run under input.mongodb, and its database under input.db_name. MongoDB has no schema layer, so the collections a command names are available in input.table_paths using the database.collection format. That includes the namespaces a bulkWrite or a renameCollection names. It does not yet include collections reached from inside an aggregation pipeline (e.g. $lookup, $unionWith, $out or $merge).

MongoDB object

SQL resources

Formal can also enforce policies specific to SQL queries. SQL Query Object

Example: Run all SQL statements in a transaction in order

You can use a workflow to create a policy suspension that ensures a sequence of SQL statements is executed in the correct order within a transaction. The workflow below accepts a list of ordered statements via its API trigger and creates a suspension that validates each statement matches the expected sequence using transaction_history.

AWS resources

Formal can also enforce policies on specific AWS Resources. These policies can be actively used for the SSH or Kubernetes.

AWS object

ECS object

EC2 object

EKS object

Kubernetes resources

Formal can enforce policies on Kubernetes API requests based on the resource being accessed. The Kubernetes context is available via input.kubernetes.

Kubernetes object

SSH resources

Formal can enforce policies on SSH sessions. The SSH context is available via input.ssh. SSH states what a session is for before any of it happens, so a session rule can decide on the command the client asked to run.

SSH object

command is the string as the client sent it. The far side runs it with a shell, so one session can ask for several things at once: match on what a rule cares about inside the command rather than comparing the whole of it. Git runs over SSH this way, which is what makes a push distinguishable from a clone: git-receive-pack writes to a repository and git-upload-pack reads from one, each naming the repository.

LLM resources

Formal can enforce policies on LLM API sessions. Use session rules to block a connection before it reaches the upstream provider, request rules to inspect and rewrite outgoing request headers or bodies, and response rules to evaluate model responses. For assessed LLM tool calls, response policies can also read input.assessment. See Assessments for its fields and an example.
Tool calls are part of the model response, so policies that inspect input.llm.tool_calls should use the response rule.

LLM object

Message object

Content part object

Tool object

Tool call object

Example: Rewrite request headers

The following policy adds request headers before the LLM request is sent to the upstream provider. Header values must be arrays of strings. Set a header to an empty array to remove it.
For the full walkthrough, see Restrict Anthropic Sign-Ins to One Org.

Example: Redact SSNs from request messages

Use a request-stage rewrite with regex.replace on input.http.body to strip sensitive values from prompts without blocking the session. This keeps coding agents usable when SSNs appear in the context window.
The rewrite replaces the full HTTP body string. Keep replacements JSON-safe so the upstream request stays valid. See HTTP body rewrites.

Example: Block specific tool calls

The following policy blocks any LLM response that includes a Bash tool call with a specific command:

MCP resources

Formal can enforce policies on MCP tool calls. The MCP context is available via input.mcp at the request and response stages when the request is a tool call.

MCP object

To block unapproved MCP servers and point agents to approved ones, see mcp_suggest_alternatives.

Example: Block a specific tool

To seal OAuth Bearer tokens for MCP clients, see Encrypt MCP OAuth Tokens.

Device

Formal can also enforce policies on specific device attributes.
This feature is only available for devices using the Formal Endpoint.

Device info object

Hardware info object

Software info object

AI agents

Formal tracks connections that originate from AI coding agents running through the Formal Endpoint. When an agent is detected, input.agent is populated with context about that agent.
input.agent is only populated for connections made via the Formal Endpoint. It is empty for direct connections.

Agent object

Example: block Claude Code in YOLO mode

Use input.agent.yolo_mode to block autonomous agents from accessing sensitive resources without per-action approval:

Policy Input Retention

Formal can optionally retain these inputs for policy backtesting where you can test policies on historical data.

Extending Policies with External Data

You can extend policies with custom data fetched by Policy Data Loaders. The data is accessible via the data object using the loader’s configured key. Example:
For more information, see Policy Data Loaders.

Legacy Stage Names

Prior to Connector v1.31.19, the Rego rule names for the request and response stages were pre_request and post_request. These legacy names still work and existing policies do not need to be updated. To migrate, rename pre_request to request and post_request to response in your policy code. Different policies can use different naming conventions.