> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lynxops.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Firewalls

> Run a local policy check before a risky tool call is executed.

`firewallTool()` wraps a tool function with a local policy check. The policy runs before the tool call. If the policy blocks, the original tool function is not executed.

## When to use this

Use firewalls for tool calls that can have side effects, cost impact, or user impact.

Examples:

* Sending an email or Slack message
* Writing to a database
* Issuing a refund
* Calling an external API
* Running a destructive or high-cost action

## How it works

You provide a `beforeCall` callback. The SDK calls it before the tool runs. The callback returns a policy decision such as `ALLOW`, `WARN`, `BLOCK`, or `REQUIRE_APPROVAL`.

The decision is recorded as part of the session. If the decision blocks the call, the SDK throws `LynxPolicyError`.

## Example

```ts theme={null}
import { LynxPolicyError } from "@lynxops/sdk";

const refund = lynx.firewallTool(
  "refund.create",
  async ({ amount }: { amount: number }) => {
    return { refunded: amount };
  },
  {
    riskLevel: "HIGH",
    sideEffect: true,
    failureMode: "FAIL_CLOSED",
    beforeCall: ({ input }) => {
      if (input.amount > 100) {
        return {
          action: "BLOCK",
          policyId: "refund-limit",
          reason: "Refund amount is over the approved limit",
          severity: "HIGH",
        };
      }

      return {
        action: "ALLOW",
        policyId: "refund-limit",
      };
    },
  },
);

try {
  await lynx.run("SupportAgent", () => refund({ amount: 500 }));
} catch (error) {
  if (error instanceof LynxPolicyError) {
    console.log(error.action, error.policyId, error.reason);
  }
}
```

## Policy decisions

| Action             | Behavior                                                                             |
| ------------------ | ------------------------------------------------------------------------------------ |
| `ALLOW`            | Runs the tool and records the policy decision.                                       |
| `WARN`             | Runs the tool and records a warning.                                                 |
| `BLOCK`            | Blocks the tool and throws `LynxPolicyError`.                                        |
| `REQUIRE_APPROVAL` | Blocks the tool and throws `LynxPolicyError`.                                        |
| `REDACT`           | Records the decision. Apply redaction in your callback before allowing the tool.     |
| `MODIFY`           | Records the decision. Apply modifications in your callback before allowing the tool. |

## Failure modes

If policy evaluation itself throws, `failureMode` decides what happens.

| Failure mode       | Behavior                                           |
| ------------------ | -------------------------------------------------- |
| `FAIL_OPEN`        | Allows the tool call and records the policy error. |
| `FAIL_CLOSED`      | Blocks the tool call.                              |
| `REQUIRE_APPROVAL` | Blocks with `REQUIRE_APPROVAL`.                    |

## What you can see in Lynx

Lynx can show:

* The policy decision for a tool call
* Whether a tool was allowed, warned, blocked, or required approval
* The policy ID and policy version
* The blocked tool call in the session timeline
* Related errors and root cause candidates

## Server availability

Firewall decisions are local. If the Lynx API is unavailable, the SDK still evaluates your policy callback. The policy decision event is queued and retried later.

## Notes

Use `FAIL_CLOSED` for high-risk actions where running the tool without a valid policy decision would be unsafe. Use `FAIL_OPEN` for low-risk actions where availability is more important than strict blocking.

## Next steps

* [Wrap LLMs and tools](/sdk/instrumentation)
* [Understand delivery behavior](/sdk/delivery)
