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

# Event Context

> How previous Events inform the check of the current Event

White Circle checks each Event against the Events that came before it. Earlier Events give the model the conversation it needs to interpret the current one, while the result describes only the Event you submitted. Any Event with content joins that conversation, not only messages; reference-only Events add nothing, because they carry no new content.

This matters for violations that are invisible in a single Event. A message like "do it for the address I gave you" is harmless alone and meaningful only after the Event that supplied the address.

## What Gets Checked

<Info>Context informs the check. It is never scored. Every Policy result and Metric describes the Event it belongs to, even when an earlier Event in the same conversation violates a Policy.</Info>

Each Event receives its own result.

## Grouping Events into a Conversation

White Circle builds context from Events that share an identifier. Use `external_session_id` for conversations that outlive a single run.

| Grouping              | Context source                                          | Lifetime                                                  |
| --------------------- | ------------------------------------------------------- | --------------------------------------------------------- |
| `external_session_id` | All previous Events with the same `external_session_id` | Durable                                                   |
| `run_id` only         | Previous Events in the same run                         | Best effort, expires after about 10 minutes of inactivity |
| Neither reused        | No context                                              | Each Event is checked alone                               |

When an Event has both, `external_session_id` selects the context and `run_id` is used only for grouping.

<Warning>Run-only context is held in a short-lived cache with no durable fallback. After roughly 10 minutes without activity in that run, a later Event is checked without its history. Send an `external_session_id` when the conversation must keep its context.</Warning>

If you omit `run_id`, White Circle generates one. A generated `run_id` is unique to that request, so those Events get no previous context.

<Steps>
  <Step title="First Event">
    Send an Event with an `external_session_id`:

    ```json theme={null}
    {
      "event": {
        "type": "message",
        "role": "user",
        "content": "My account number is 4471",
        "event_id": "evt_user_001"
      },
      "environment_id": "environment_123",
      "external_session_id": "conversation_456",
    }
    ```
  </Step>

  <Step title="Later Event">
    Send the next Event with the same `external_session_id`. It does not have to be a message; here a tool returns the stored record:

    ```json theme={null}
    {
      "event": {
        "type": "tool",
        "name": "lookup_account",
        "output": { "account": "4471", "holder": "A. Rivera" },
        "event_id": "evt_tool_001"
      },
      "environment_id": "environment_123",
      "external_session_id": "conversation_456",
    }
    ```
  </Step>

  <Step title="Third Event">
    A later message is checked against everything before it:

    ```json theme={null}
    {
      "event": {
        "type": "message",
        "role": "user",
        "content": "Post it publicly",
        "event_id": "evt_user_002"
      },
      "environment_id": "environment_123",
      "external_session_id": "conversation_456",
    }
    ```
  </Step>

  <Step title="What the Model Sees">
    White Circle checks `evt_user_002` against all three Events:

    ```json theme={null}
    [
      { "role": "user", "content": "My account number is 4471" },
      { "role": "tool", "content": "{\"account\":\"4471\",\"holder\":\"A. Rivera\"}" },
      { "role": "user", "content": "Post it publicly" }
    ]
    ```

    The tool output enters the conversation with the `tool` role, and `agent.instructions` would enter as `system`. The result belongs to `evt_user_002` alone.
  </Step>
</Steps>

## Context in a Batch

Events in a `POST /api/events` batch become context for the Events after them, in the order you list them in the `events` array.

A batch can mix Event types, and each one becomes context for those after it:

```json theme={null}
{
  "events": [
    { "type": "message", "event_id": "evt_1", "role": "user", "content": "Email the invoice to the address I gave you" },
    { "type": "agent", "event_id": "evt_2", "name": "billing_agent", "instructions": "Send invoices only to verified addresses" },
    { "type": "tool", "event_id": "evt_3", "name": "send_email", "arguments": { "to": "a.rivera@example.com" } },
    { "type": "tool", "event_id": "evt_4", "name": "send_email", "output": { "status": "sent" } }
  ],
  "environment_id": "environment_123",
  "external_session_id": "conversation_456"
}
```

Each Event is checked against the conversation up to and including itself:

| Event   | Context it is checked with                               |
| ------- | -------------------------------------------------------- |
| `evt_1` | Previous Events in the conversation, then `evt_1`        |
| `evt_2` | The same previous Events, then `evt_1`, `evt_2`          |
| `evt_3` | The same previous Events, then `evt_1`, `evt_2`, `evt_3` |
| `evt_4` | The same previous Events, then `evt_1` through `evt_4`   |

<Note>Array order defines context, not arrival order. White Circle checks a batch concurrently, and no Event is ever checked against an Event listed after it.</Note>

List Events in the order they happened. Submitting an assistant reply before the user message it answers gives the model a conversation your application never produced.

<Tip>To check an Event in isolation, submit it without reusing an `external_session_id` or `run_id`. Events always use the context available to them.</Tip>
