# Sessions

Sessions group function runs that belong to the same user flow, conversation, or job.

Add `meta.sessions` to an event when you want the Inngest dashboard to show all runs related to the same external ID. For example, all runs started by messages in the same AI conversation can share a `conversation_id` session.

Sessions do not change which functions run. They add event metadata that makes related runs easier to find and inspect.

> **Callout:** When sending events with the TypeScript SDK, meta.sessions is supported in v4.7.0 and later.

## When to use sessions

> **Info:** Sessions is optimized for historical data, with a few-minute lag before data appears, so it’s not intended for monitoring live-executing runs.

Use sessions when you already have a domain ID that ties multiple function runs together.

Common examples include AI conversations, agent runs, support tickets, imports, customer workflows, and long-running business processes.

For one-off filtering, use [Insights](/docs-markdown/platform/monitor/insights?ref=docs-sessions) or the normal runs search instead. Sessions are best for IDs you expect to search and inspect repeatedly.

> **Callout:** Sessions are for high-cardinality identifiers — one ID per conversation, ticket, or job. They are not for low-cardinality labels like environment: prod. For label-style filtering, use Insights instead.

## Add sessions to an event

Add `sessions` inside the event's top-level `meta` object.

```ts
import { inngest } from "./client";

await inngest.send({
  name: "app/message.created",
  data: {
    messageId: "msg_01JYY8R9C5R6VAW5EJ0P4K7V90",
    conversationId: "conv_1234",
  },
  meta: {
    sessions: {
      conversation_id: "conv_1234",
    },
  },
});
```

The object key is the session key. The value is the session ID.

In the example above:

- `conversation_id` is the session key
- `conv_1234` is the session ID

You can use the same session key across many events. Each unique session ID becomes a session in the dashboard.

> **Callout:** Webhook transforms can also add sessions by returning meta.sessions in the transformed event. See webhook transforms for more details.

## Sessions and steps

Sessions follow events, not runs:

- **`step.sendEvent()`** attaches `meta.sessions` the same way as `inngest.send()`.
- **`step.invoke()`** accepts explicit `meta.sessions`. Sessions are **not** inherited from the calling run — the invoked function only joins a session if you pass one.
- **`step.waitForEvent()`** does not match on sessions; the matched event's sessions are returned on `result.meta?.sessions`.
- **Failure and lifecycle events** (`inngest/function.finished`, `.failed`, `.cancelled`) carry the `meta.sessions` of the event they report on, so an `onFailure` handler stays in the same session as the run that failed.

For example, pass sessions explicitly when invoking another function:

```ts
await step.invoke("summarize-conversation", {
  function: summarizeConversation,
  data: { conversationId: event.data.conversationId },
  meta: {
    sessions: {
      conversation_id: event.data.conversationId,
    },
  },
});
```

## Supported values

Session IDs can be strings or finite numbers. Numbers are stored as strings. Other value types, including booleans, `null`, objects, and arrays, are rejected.

```ts
await inngest.send({
  name: "app/agent.step.completed",
  data: {
    stepId: "step_1",
  },
  meta: {
    sessions: {
      conversation_id: "conv_1234",
      thread_id: 29563,
    },
  },
});
```

Use stable IDs that are safe to show in the dashboard. Do not store secrets or sensitive personal data in session IDs.

## Limits

- Each event can include up to 5 entries in `meta.sessions`.
- For non-batched functions, that means the run can be associated with up to 5 sessions.
- For batched functions, one run can be triggered by multiple events. In that case, Inngest combines the sessions from every event in the batch, orders them alphanumerically, and keeps the first 25 unique session key/ID pairs for the run.
- Session keys and IDs cannot be empty.
- Session IDs must be strings or finite numbers. Numbers are normalized to strings.

| Field       | Limit     |
| ----------- | --------- |
| Session key | 128 bytes |
| Session ID  | 512 bytes |

Session ID limits apply after numbers are normalized to strings.

## Choose a good session key

Use a session key for the kind of thing you want to inspect later.

Good examples:

- `conversation_id`
- `agent_run_id`
- `ticket_id`
- `workflow_id`
- `import_id`

Avoid putting the session ID in the session key. For example, use this:

```ts
meta: {
  sessions: {
    conversation_id: "conv_1234",
  },
}
```

Not this:

```ts
meta: {
  sessions: {
    "conversation_id:conv_1234": "true",
  },
}
```

Session IDs are treated as opaque strings. They can contain characters like `:` or `/`, and the dashboard will keep the session key and ID separate.

## View sessions in the dashboard

Open the Inngest dashboard and select an environment.

Go to **AI > Sessions**.

Search for a session key, such as `conversation_id`.

![The Sessions search page filtered by a session key](/assets/docs/features/events-triggers/sessions/search.png)

The results page shows each session ID for that key, along with:

- number of runs
- failed runs and failure rate
- last active time
- functions seen in that session

Click a session row to open the detail page. The detail page shows the runs for that specific session key and ID.

> **Callout:** Sessions are scoped to the selected environment. If you do not see a session, check that you are in the environment where the event was sent.

## Use sessions for historical search

Sessions use the same indexed event and run data that powers [Insights](/docs-markdown/platform/monitor/insights?ref=docs-sessions). This index is designed for search, filtering, and investigation across activity that Inngest has recorded.

Because the index is updated asynchronously, newly sent events, recently started runs, and status changes may take a short time to appear in Sessions. Treat Sessions as a historical view for finding and inspecting related runs, not as a realtime source of truth for the current state of an active workflow.

## Related docs

- [Agent Evals overview](/docs-markdown/learn/agent-evals?ref=docs-sessions) to understand how sessions, traces, scores, and experiments fit together
- [Score a function run](/docs-markdown/features/inngest-functions/steps-workflows/scoring?ref=docs-sessions) for attaching outcomes to runs and steps