# Akamai Firewall for AI Policy

[Akamai Firewall for AI](https://www.akamai.com/products/firewall-for-ai)
inspects requests bound for AI applications and detects threats such as prompt
injection, jailbreak attempts, sensitive data exposure, and toxic content.

This policy sends each incoming request to Akamai's detect endpoint before it
reaches your handler. If Akamai returns a rule with a `deny` action, the request
is blocked with a `403 Forbidden`. Rules with an `alert` action (Akamai
"Monitor" mode) are logged by default but allowed through, configurable via the
`onWarn` setting.

Pair with the
[Akamai Firewall for AI - Outbound](/docs/policies/akamai-firewall-for-ai-outbound)
policy to also inspect upstream responses before they're returned to the client.

## Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

```json title="config/policies.json"
{
  "name": "my-akamai-firewall-for-ai-inbound-policy",
  "policyType": "akamai-firewall-for-ai-inbound",
  "handler": {
    "export": "AkamaiFirewallForAiInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "configurationId": "$env(AKAMAI_FIREWALL_FOR_AI_CONFIGURATION_ID)",
      "api-key": "$env(AKAMAI_FIREWALL_FOR_AI_API_KEY)",
      "capture": {
        "body": true,
        "headers": false,
        "url": false,
        "queryString": false
      },
      "onWarn": "log",
      "throwOnError": true
    }
  }
}
```

### Policy Configuration

- `name` <code className="text-green-600">&lt;string&gt;</code> - The name of your policy instance. This is used as a reference in your routes.
- `policyType` <code className="text-green-600">&lt;string&gt;</code> - The identifier of the policy. This is used by the Zuplo UI. Value should be `akamai-firewall-for-ai-inbound`.
- `handler.export` <code className="text-green-600">&lt;string&gt;</code> - The name of the exported type. Value should be `AkamaiFirewallForAiInboundPolicy`.
- `handler.module` <code className="text-green-600">&lt;string&gt;</code> - The module containing the policy. Value should be `$import(@zuplo/runtime)`.
- `handler.options` <code className="text-green-600">&lt;object&gt;</code> - The options for this policy. [See Policy Options](#policy-options) below.

### Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

- `configurationId` **(required)** <code className="text-green-600">&lt;string&gt;</code> - Your Akamai Firewall for AI Configuration ID. This is the ID of the configuration in the Akamai Control Center that defines which detection rules to apply.
- `api-key` **(required)** <code className="text-green-600">&lt;string&gt;</code> - Your Akamai Firewall for AI API key, sent as the `Fai-Api-Key` header on each detect call.
- `capture` <code className="text-green-600">&lt;object&gt;</code> - Controls which parts of the incoming request are sent to Akamai for inspection. Akamai's detect endpoint receives the captured fields concatenated into a single labeled text payload as `llmInput`.
  - `body` <code className="text-green-600">&lt;boolean&gt;</code> - Include the request body. Only text-based content types (JSON, XML, form-encoded, text/\*) are sent; binary bodies are skipped. The body is read from a clone of the request so the upstream still receives it unchanged. Defaults to `true`.
  - `headers` <code className="text-green-600">&lt;boolean&gt;</code> - Include the request headers. By default `Authorization`, `Proxy-Authorization`, `Cookie`, and `Set-Cookie` are stripped — see the `dangerouslyInclude*` flags to override. Defaults to `false`.
  - `url` <code className="text-green-600">&lt;boolean&gt;</code> - Include the request URL (origin and path, query string excluded). Enable `queryString` separately if you also want the query string. Defaults to `false`.
  - `queryString` <code className="text-green-600">&lt;boolean&gt;</code> - Include the request query string. Query strings sometimes contain credentials or session tokens — leave this off unless you want Akamai to see them. Defaults to `false`.
  - `dangerouslyIncludeAuthorizationHeader` <code className="text-green-600">&lt;boolean&gt;</code> - If `headers` is true, also include the `Authorization` and `Proxy-Authorization` headers. Off by default because these typically contain bearer tokens. Defaults to `false`.
  - `dangerouslyIncludeCookieHeader` <code className="text-green-600">&lt;boolean&gt;</code> - If `headers` is true, also include the `Cookie` header. Off by default because cookies often carry session credentials. Defaults to `false`.
- `onWarn` <code className="text-green-600">&lt;string&gt;</code> - Behavior when Akamai returns a rule with `action: "alert"` (Akamai's Monitor mode). `log` writes a warning and lets the request through, `block` treats the alert like a deny, `none` is silent. Allowed values are `log`, `block`, `none`. Defaults to `"log"`.
- `throwOnError` <code className="text-green-600">&lt;boolean&gt;</code> - If true (the default), the policy throws when the Akamai detect call itself fails (network error, 5xx, malformed response). Set to false to fail open and allow the request through when Akamai is unreachable. Defaults to `true`.
- `detectUrl` <code className="text-green-600">&lt;string&gt;</code> - Override the Akamai Firewall for AI detect endpoint URL. The literal `{configurationId}` is replaced with the configured ID. Defaults to `https://aisec.akamai.com/fai/v1/fai-configurations/{configurationId}/detect`. Useful for regional Akamai endpoints or for pointing tests at a mock server.

## Using the Policy

## Setup

1. In the Akamai Control Center, create a Firewall for AI configuration and note
   its **Configuration ID**.
2. Generate an **API key** for the configuration.
3. Add the credentials to your Zuplo project's environment variables (or paste
   them directly into the policy options):

   ```text
   AKAMAI_FIREWALL_FOR_AI_CONFIGURATION_ID=your-configuration-id
   AKAMAI_FIREWALL_FOR_AI_API_KEY=your-api-key
   ```

4. Add the policy to any route that should be inspected by Akamai.

## What gets sent to Akamai

Akamai's detect endpoint accepts a single text string in `llmInput`. The
`capture` option controls which parts of the incoming request are concatenated
into that string:

| Field         | Default | Notes                                                                               |
| ------------- | ------- | ----------------------------------------------------------------------------------- |
| `body`        | `true`  | Cloned before reading; only text content types (JSON, XML, form, text/\*) are sent. |
| `headers`     | `false` | `Authorization`, `Proxy-Authorization`, `Cookie`, and `Set-Cookie` are stripped.    |
| `url`         | `false` | Origin and path only.                                                               |
| `queryString` | `false` | Off by default — query strings often contain credentials or session tokens.         |

### Including credential headers

If you do want Akamai to see credential-bearing headers (for example, to detect
tokens that have been leaked into custom headers), opt in explicitly:

```json
{
  "name": "akamai-firewall-for-ai-inbound",
  "policyType": "akamai-firewall-for-ai-inbound",
  "handler": {
    "export": "AkamaiFirewallForAiInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "configurationId": "$env(AKAMAI_FIREWALL_FOR_AI_CONFIGURATION_ID)",
      "api-key": "$env(AKAMAI_FIREWALL_FOR_AI_API_KEY)",
      "capture": {
        "body": true,
        "headers": true,
        "dangerouslyIncludeAuthorizationHeader": true
      }
    }
  }
}
```

## Handling alert vs deny

Akamai rules can be configured with one of two actions:

- **`deny`** — the request is always blocked with a `403 Forbidden`.
- **`alert`** — Akamai detected a match but configured the rule for monitoring
  only. The `onWarn` option controls how this policy reacts:
  - `"log"` (default) writes a structured warning to the Zuplo logs and allows
    the request through.
  - `"block"` treats `alert` the same as `deny` — useful in staging when rolling
    out new rules.
  - `"none"` silently allows the request through with no log line.

## Failure modes

By default the policy is **fail-closed**: if the call to Akamai itself fails
(network error, 5xx, malformed response), the policy throws and the request is
rejected. This is the safe default for a security control. To fail open when
Akamai is unreachable, set `throwOnError: false`.

## Pair with the outbound policy

Add
[Akamai Firewall for AI - Outbound](/docs/policies/akamai-firewall-for-ai-outbound)
to the same route to also inspect the upstream response before it's sent back to
the client. The two policies share the same configuration shape.

Read more about [how policies work](/articles/policies)
