# How to Trigger Policies Based on Audit Events Using the Event Matcher Policy in authentik

> Learn how to trigger authentik policies based on audit events. Use the Event Matcher Policy to evaluate events by configuring criteria like action, client IP, and application.

- Repository: [Authentik Security/authentik](https://github.com/goauthentik/authentik)
- Tags: how-to-guide
- Published: 2026-08-14

---

**Use the Event Matcher Policy in authentik to evaluate audit events by placing an event object in the request context and configuring match criteria such as action, client IP, application, model, or AKQL query.**

The Event Matcher Policy is a specialized policy type in authentik that evaluates whether an incoming audit event matches specific criteria. This enables fine-grained automation—such as sending notifications or triggering flows—based on actions that occur within your identity infrastructure. This guide explains how the policy works, how to configure it, and how to integrate it with Notification Rules.

## How the Event Matcher Policy Works

The Event Matcher Policy inherits from the base `Policy` class in [`authentik/policies/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/models.py). Like all policies, it implements a `passes(request)` method that returns a `PolicyResult` indicating whether the policy passes or fails.

The policy's implementation in [`authentik/policies/event_matcher/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/models.py) follows a strict evaluation flow:

1. **Context validation** — The policy first verifies that `request.context["event"]` exists. If no event is present, the policy immediately fails.

2. **Field matching** — The policy evaluates up to five optional criteria. All configured criteria must match for the policy to pass.

3. **Result aggregation** — Each matcher returns a `PolicyResult` or `None` (when unset). Results are combined with logical AND.

## Event Matcher Policy Configuration Fields

The following fields control how events are matched:

| Field | Purpose | Source Method |
|-------|---------|---------------|
| `action` | Matches the event's `action` string exactly | `passes_action` |
| `client_ip` | Exact match on the source IP address | `passes_client_ip` |
| `app` | Matches the originating application name | `passes_app` |
| `model` | Matches the event's model identifier | `passes_model` |
| `query` | Evaluates an AKQL expression against the event | `passes_query` |

Empty fields act as wildcards. The policy only enforces criteria that you explicitly configure.

## AKQL Query Support for Advanced Matching

The `query` field provides the most flexible matching capability. When configured, the policy constructs a temporary **InlineSchema** based on the read-only `EventViewSet` from [`authentik/events/api/events.py`](https://github.com/goauthentik/authentik/blob/main/authentik/events/api/events.py). It then executes `apply_search` from **django-ql** to evaluate your AKQL expression against the event.

AKQL queries can reference any event attribute exposed by the Event API, including nested context fields:

```python

# Match events where a specific application was involved

query='context.authorized_application.name = "admin"'

# Match events where the username ends with "admin"

query='context.user.username__endswith = "admin"'

# Match failed authentications with specific error patterns

query='action = "login_failed" and context.reason__icontains = "password"'

```

## Creating an Event Matcher Policy

### Via the Python API

```python
from authentik.policies.event_matcher.models import EventMatcherPolicy

# Match failed logins from a specific IP

policy = EventMatcherPolicy.objects.create(
    name="Failed login from 192.0.2.0",
    action="login_failed",
    client_ip="192.0.2.0",
)

# Match using AKQL for complex conditions

complex_policy = EventMatcherPolicy.objects.create(
    name="Admin portal suspicious activity",
    query='context.authorized_application.name = "admin" and action__contains = "update"',
)

```

### Via the REST API

```http
POST /api/v3/policies/event_matcher/
Content-Type: application/json

{
  "name": "Failed login from 192.0.2.0",
  "action": "login_failed",
  "client_ip": "192.0.2.0"
}

```

### Via the REST API with AKQL Query

```http
POST /api/v3/policies/event_matcher/
Content-Type: application/json

{
  "name": "Admin application modifications",
  "query": "context.authorized_application.name = \"admin\" and action = \"model_updated\""
}

```

## Integrating with Notification Rules

The primary consumer of the Event Matcher Policy is the **Notification Rule** system. Notification Rules automatically evaluate policies when events occur, placing the event in the request context.

Here's how to bind a policy to a Notification Rule:

```python
from authentik.events.models import NotificationRule, NotificationWebhook
from authentik.policies.event_matcher.models import EventMatcherPolicy

# Create the matching policy

login_alert_policy = EventMatcherPolicy.objects.create(
    name="External IP login alert",
    action="login",
    query='not context.client_ip__startswith = "10."',
)

# Create or retrieve a notification transport

webhook = NotificationWebhook.objects.get(name="Security Slack")

# Create the rule and attach the policy

rule = NotificationRule.objects.create(
    name="External login notifications",
    severity="warning",
)
rule.policies.add(login_alert_policy)
rule.transports.add(webhook)

```

## Architecture and Data Flow

When an event triggers a Notification Rule evaluation, the following flow occurs:

```

Event generated → Stored in DB (authentik/events/models.py)
      │
      ▼
NotificationRule evaluates → request.context["event"] = event
      │
      ▼
EventMatcherPolicy.passes(request)
      │    ├── Check event exists in context
      │    ├── Evaluate action match (if set)
      │    ├── Evaluate client_ip match (if set)
      │    ├── Evaluate app match (if set)
      │    ├── Evaluate model match (if set)
      │    └── Evaluate AKQL query (if set)
      │
      ▼
PolicyResult (pass/fail)

```

If the policy passes, the Notification Rule continues execution—delivering notifications to configured transports. If it fails, the rule aborts silently.

## Validation and API Constraints

The policy serializer in [`authentik/policies/event_matcher/api.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/api.py) enforces a critical constraint: **at least one match criterion must be configured**. This prevents creation of "wildcard-only" policies that would match every event indiscriminately.

Attempting to create a policy with all fields empty returns:

```json
{
  "non_field_errors": ["At least one of action, client_ip, app, model, or query must be set."]
}

```

## Testing Event Matcher Policies

The test suite in [`authentik/policies/event_matcher/tests.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/tests.py) validates all matching scenarios. Key test patterns include:

- Verifying policy failure when no event exists in context
- Testing exact string matches on action, IP, app, and model fields
- Validating AKQL query evaluation against complex event structures
- Confirming that multiple criteria combine with AND logic

Run the tests with:

```bash
python -m pytest authentik/policies/event_matcher/tests.py -v

```

## Key Source Files and References

- **Policy model implementation** — [`authentik/policies/event_matcher/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/models.py)
- **API serializers and viewset** — [`authentik/policies/event_matcher/api.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/api.py)
- **Test coverage** — [`authentik/policies/event_matcher/tests.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/tests.py)
- **Official documentation** — [`website/docs/customize/policies/types/event-matcher.md`](https://github.com/goauthentik/authentik/blob/main/website/docs/customize/policies/types/event-matcher.md)
- **Base policy framework** — [`authentik/policies/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/models.py)
- **Event model definitions** — [`authentik/events/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/events/models.py)
- **Event API schema** — [`authentik/events/api/events.py`](https://github.com/goauthentik/authentik/blob/main/authentik/events/api/events.py)

## Summary

- The **Event Matcher Policy** evaluates audit events placed in `request.context["event"]` and returns pass/fail based on configured criteria.
- Match using **action**, **client_ip**, **app**, **model**, or **AKQL query**—all configured criteria must match.
- **AKQL queries** provide the most flexibility, leveraging django-ql against the EventViewSet schema.
- Primary integration is with **Notification Rules**, which automatically populate the event context during evaluation.
- The API enforces that **at least one criterion must be set** to prevent wildcard-only policies.

## Frequently Asked Questions

### What happens if no event exists in the request context?

The policy automatically fails with a failing `PolicyResult`. The `passes` method in [`authentik/policies/event_matcher/models.py`](https://github.com/goauthentik/authentik/blob/main/authentik/policies/event_matcher/models.py) explicitly checks for `request.context.get("event")` and returns early if missing. This design prevents the policy from accidentally matching non-event evaluation contexts.

### Can I use multiple match criteria together?

Yes. When you configure multiple fields (for example, `action` and `client_ip`), the policy applies **logical AND**—all configured criteria must match for the policy to pass. Empty fields are ignored entirely. This allows precise targeting such as "login events from a specific IP" without affecting other event types from that IP.

### How do I test my AKQL query before creating a policy?

Use the Events API to inspect event structure, then validate AKQL syntax against the `EventViewSet` schema. The `query` field accepts any expression valid for django-ql against the fields exposed in [`authentik/events/api/events.py`](https://github.com/goauthentik/authentik/blob/main/authentik/events/api/events.py). Start with simple equality checks, then add operators like `__contains`, `__startswith`, or `__endswith` for partial matching.

### What's the difference between Event Matcher Policy and other authentik policy types?

Most authentik policies evaluate the current user, device, or request properties. The **Event Matcher Policy** is unique in evaluating **historical or in-flight audit events**—enabling reactive automation based on "something that happened" rather than "who is asking." This makes it essential for security monitoring, compliance alerting, and operational event routing.