
# Akamai AI Firewall Policy

:::note{title="AI Gateway Policy"}

This policy is for use with the [AI Gateway](/docs/ai-gateway/introduction). See
the AI Gateway documentation to learn how to configure and govern AI models
with Zuplo.

:::

The Akamai AI Firewall policy scans AI Gateway prompts and completions with
Akamai Firewall for AI. One inbound policy protects both request and response
content, including streaming responses, and blocks content that an Akamai rule
denies.

For runtime inspection, the policy denies unknown endpoint shapes and handled
Akamai detection-call failures by default. If a recognized request or successful
response has an unparseable JSON body, the policy skips scanning that body and
passes it through. Detection rules and categories are configured in Akamai
Control Center.

## Configuration

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

```json title="config/policies.json"
{
  "name": "my-akamai-ai-firewall-v2-inbound-policy",
  "policyType": "akamai-ai-firewall-v2-inbound",
  "handler": {
    "export": "AkamaiAIFirewallV2InboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "configurationId": "$env(AKAMAI_AI_FIREWALL_CONFIGURATION_ID)",
      "api-key": "$env(AKAMAI_AI_FIREWALL_API_KEY)"
    }
  }
}
```

### 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-ai-firewall-v2-inbound`.
- `handler.export` <code className="text-green-600">&lt;string&gt;</code> - The name of the exported type. Value should be `AkamaiAIFirewallV2InboundPolicy`.
- `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> - The configuration ID of the AI Firewall.
- `api-key` **(required)** <code className="text-green-600">&lt;string&gt;</code> - The API key for the AI Firewall.
- `applicationId` <code className="text-green-600">&lt;string&gt;</code> - The application ID to identify this usage of the AI Firewall (optional).
- `streamingAccumulation` <code className="text-green-600">&lt;object&gt;</code> - Configuration for accumulating and validating streaming responses.
  - `enabled` <code className="text-green-600">&lt;boolean&gt;</code> - Enable accumulation and validation of streaming responses. Defaults to `true`.
  - `eventsInterval` <code className="text-green-600">&lt;number&gt;</code> - Number of SSE events to accumulate before checking with Akamai (default: 5). Defaults to `5`.
  - `checkIntervalMs` <code className="text-green-600">&lt;number&gt;</code> - Time interval in milliseconds for periodic checks (alternative to chunk count).
- `endpoints` <code className="text-green-600">&lt;string[]&gt;</code> - The endpoint shapes this policy applies to. Omit to apply to all (openai-chat, openai-responses, anthropic-messages).
- `onUnknownShape` <code className="text-green-600">&lt;string&gt;</code> - What to do when the request shape cannot be inspected. As a guardrail, this policy defaults to 'deny' (fail closed) so uninspectable content is never served. Allowed values are `deny`, `skip`. Defaults to `"deny"`.
- `onError` <code className="text-green-600">&lt;string&gt;</code> - What to do when the Akamai detect call itself fails (invalid API key, rate limit, outage). 'block' (the default) fails closed and returns a 502 so unverified content is never served; 'allow' fails open and lets the request through without inspection. Allowed values are `block`, `allow`. Defaults to `"block"`.

## Using the Policy

# Akamai AI Firewall

The Akamai AI Firewall policy sends prompts and completions to
[Akamai Firewall for AI](https://www.akamai.com/products/firewall-for-ai) and
blocks content that your Akamai configuration denies. One inbound policy covers
both directions: it scans the request before the provider call and the response
afterward, including streaming responses.

Detection rules and their categories live in Akamai Control Center. The policy
enforces rules configured to deny; rules configured only to alert do not block
the request.

## Configure the policy

Create or select an Akamai Firewall for AI configuration and API key. Declare
the policy once in `config/policies.json`, then add the declaration to each
application policy chain that should be protected. To protect new applications
by default, include it in the team's policy template.

```json
{
  "name": "akamai-ai-firewall-v2-inbound",
  "policyType": "akamai-ai-firewall-v2",
  "handler": {
    "export": "AkamaiAIFirewallV2InboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "configurationId": "your-configuration-id",
      "api-key": "$env(AKAMAI_AI_FIREWALL_API_KEY)"
    }
  }
}
```

When an application chain entry should inherit these credentials, omit the
entry's `options`. Entry options replace the declaration's complete options
object; they do not merge with it.

## Options

| Option                                  | Default    | What it does                                                    |
| --------------------------------------- | ---------- | --------------------------------------------------------------- |
| `configurationId`                       | Required   | Selects the Akamai firewall configuration.                      |
| `api-key`                               | Required   | Authenticates to Akamai. The property name includes the hyphen. |
| `applicationId`                         | Unset      | Supplies an optional Akamai application identifier.             |
| `endpoints`                             | All shapes | Limits inspection to selected AI Gateway endpoint shapes.       |
| `onUnknownShape`                        | `deny`     | Denies or skips a request whose shape cannot be inspected.      |
| `onError`                               | `block`    | Blocks or allows traffic when the Akamai detection call fails.  |
| `streamingAccumulation.enabled`         | `true`     | Enables response inspection for streaming requests.             |
| `streamingAccumulation.eventsInterval`  | `5`        | Buffers this many stream events between checks.                 |
| `streamingAccumulation.checkIntervalMs` | Unset      | Also runs checks on a timer when configured.                    |

Unknown option keys and incomplete credentials are rejected. Invalid options
fail closed so a broken chain never silently disables the guardrail.

## Streaming behavior

For streaming responses, the gateway withholds each batch of events until the
Akamai check passes. This prevents denied content from reaching the client, but
the buffering and network check add latency. If a later batch is denied, the
stream ends with a content-filter stop rather than changing the HTTP status of a
response that has already started.

## Block and failure behavior

A denied request or non-streaming response returns `400` in the request shape's
native error format and includes the Akamai rule ID. Anthropic Messages uses an
Anthropic-style error; Chat Completions and Responses use an OpenAI-style error.
Provider error responses are not scanned.

| Situation                                                               | Result                                             |
| ----------------------------------------------------------------------- | -------------------------------------------------- |
| Options are invalid or incomplete                                       | Request rejected before unguarded traffic can run. |
| The endpoint shape cannot be inspected                                  | `400`, with code `guardrail_uninspectable`.        |
| A recognized request body cannot be parsed                              | Request continues without input inspection.        |
| A successful response body cannot be parsed                             | Response passes through without output inspection. |
| Akamai rejects the credentials, rate-limits the call, or is unavailable | `502`, with code `guardrail_unavailable`.          |
| The endpoint is excluded by `endpoints`                                 | Request passes through without inspection.         |

Setting `onError` to `allow` changes service failures to fail open. An expired
credential can then leave the gateway returning successful responses without
inspection, so monitor firewall findings and sudden drops in block volume.

## Additional resources

- [Akamai Firewall for AI](https://www.akamai.com/products/firewall-for-ai)
- [Akamai AI security solutions](https://www.akamai.com/solutions/security/ai-security)

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