# Sessions and contexts (/docs/concepts/sessions)



A2A groups related messages with a **`contextId`**. Each wrapper maps that to a persistent session in its backend, so a follow-up message on the same context continues the same conversation with full memory.

| Wrapper           | `contextId` maps to                                      |
| ----------------- | -------------------------------------------------------- |
| `a2a-copilot`     | a Copilot session                                        |
| `a2a-claude`      | a Claude session, resumed with the SDK's `resume` option |
| `a2a-codex`       | a Codex thread                                           |
| `a2a-opencode`    | an OpenCode session                                      |
| `a2a-antigravity` | an Antigravity session                                   |

## Using it [#using-it]

Pass the same `contextId` on every message in a conversation. If you omit it, the server creates one and returns it in the response, which you then reuse.

```json
{
  "jsonrpc": "2.0", "id": "2", "method": "message/send",
  "params": {
    "message": {
      "kind": "message", "messageId": "m2", "role": "user",
      "contextId": "<the contextId from the first response>",
      "parts": [{ "kind": "text", "text": "Now add tests for that." }]
    }
  }
}
```

## Configuration [#configuration]

```json
{
  "session": {
    "reuseByContext": true,
    "ttl": 3600000,
    "cleanupInterval": 300000
  }
}
```

| Field             | Meaning                                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------------------- |
| `reuseByContext`  | Reuse one backend session per `contextId`                                                            |
| `ttl`             | Milliseconds until a session expires. `0` disables expiry                                            |
| `cleanupInterval` | Background sweep that reclaims expired sessions. `0` disables it, and it is only used when `ttl > 0` |

<Callout type="warn" title="TTL is measured from creation">
  In `a2a-claude`, `ttl` counts from when the session was **created**, not from its last use, and defaults to `0` (no expiry). A positive value resets even an active conversation on a fixed schedule. When a session expires, the next turn on that `contextId` starts a fresh session with no memory of earlier turns. Defaults and exact semantics can differ per wrapper, so check the package reference.
</Callout>

## Multi-agent conversations [#multi-agent-conversations]

In a multi-agent workflow each agent keeps its own session. A planner can reuse one `contextId` across calls to each agent so every agent maintains its own history, as the [crew example](/docs/getting-started/multi-agent-crew) does.
