Skip to main content
Hooks extend policy evaluation with data or logic unavailable in the standard policy input. Each hook receives the current policy input and returns JSON for Rego. Common use cases include:
  • Fetching a risk score from an internal service
  • Checking temporary approvals or maintenance windows
  • Adding business context from an existing API
  • Normalizing an external response into a stable object for policies
Hooks run in the access path. Keep their execution time and returned data as small as possible.

Writing Hooks

Hooks are written in JavaScript or TypeScript. The source must provide a default exported function, which may be synchronous or asynchronous.
The function accepts the following arguments: Only input is required. Hooks that do not use environment variables or caching may omit the other arguments. The return value must be representable as JSON. Objects, arrays, strings, numbers, booleans, and null are supported. The top-level value cannot be undefined, a function, or a symbol. Circular objects and bigint values are also unsupported. Imports are not supported. All required logic must be included in the hook source.

Status

Use draft status while developing a hook. Activate it before creating or updating a policy that references it.

Policy Evaluation

Policies reference hook results through input.hooks.<name>. This policy blocks a request when the risk hook returns a score of 5 or greater:
Formal first evaluates the parts of each policy that do not depend on hooks. It then invokes only the hooks required to complete the policy decision. Each required hook receives the policy input for the current session, request, or response stage. Formal adds the returned value to input.hooks. It then completes the policy evaluation. Formal invokes a shared hook once when several applicable policies reference it. Hook references must use a fixed name. Both input.hooks.risk and input.hooks["risk"] are valid. Dynamic references such as input.hooks[hook_name] are not supported.
A policy can only reference an active hook. Formal rejects references to missing or draft hooks when validating the policy.

Complete Example

The following hook requests a risk score and caches the result for 60 seconds:
This hook requires the following configuration:

Network Access

Network access is denied by default. A hook can use fetch only for destinations included in its allowed network hosts. The allowlist accepts hostnames, IP addresses, and IP ranges in CIDR notation. Enter the destination without a scheme, path, or port. An allowed destination permits connections to all ports on that host or range. For example, allow risk.example.com rather than https://risk.example.com/v1/score.

Environment Variables

The env argument contains only variables named in the hook’s allowed environment variables. Formal omits allowed variables that are not set on the evaluating endpoint. No environment variables are available by default. Required variables must be configured on every Connector or Endpoint that may evaluate the hook.
A hook can send an allowed environment variable to an allowed network host. Only grant both capabilities when the hook requires them.

Caching

The cache argument stores JSON-compatible values between evaluations of the same hook. Each hook’s cache is isolated from other hooks.
cache.get(key) returns the stored value. It returns undefined when the key is missing or expired. cache.set(key, value, ttlSeconds) stores the value for the specified number of seconds. Writes are immediately visible to later reads during the same evaluation. To share cached values across multiple instances of the same Connector, enable clustering. Replication between instances is eventually consistent: an evaluation sees its own writes, but other Connector instances may not see them immediately. Cache availability and persistence failures do not fail an otherwise successful hook evaluations. Writes are applied after successful execution and failures are logged.
Caching is in-memory only and does not persist across Connector or Endpoint restarts. Cache entries may be unavailable or expire at any time. Treat the cache as an optimization rather than an authoritative data source.

Limits

Execution Limits

Cache Limits

Output and cache value limits use UTF-8 byte counts after JSON serialization. Cache key limits also use UTF-8 byte counts.

Errors

A hook evaluation fails when the hook:
  • Exceeds its configured timeout
  • Throws an error or returns a rejected promise
  • Attempts a network request to a destination that is not allowed
  • Returns a value that cannot be represented as JSON
  • Returns more than 1 MiB of serialized JSON
  • Exceeds a cache limit
When a required hook fails, the policy evaluation returns an error. Formal does not continue with an absent or partial hook result. Use explicit timeouts, handle upstream errors, and keep external dependencies reliable.

Next Steps

Policy Evaluation

Review the input available at each policy stage

Policy Examples

Explore common policy patterns