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

# Context

> List, retrieve, and delete caller-visible A2A conversation contexts.

**Metadata**

| Field | Value |
| - | - |
| Canonical URI | `https://docs.aion.to/a2a/extensions/aion/context/1.0.0` |
| Issuer | `aion` |
| Version | `1.0.0` |
| Activation | This extension is declarative. It will always be active and does not require activation. |
| Related Methods | `GetContexts`, `GetContext`, `DeleteContext` |

## Overview

The Context extension provides one caller-scoped conversation-history contract with three
operations over JSON-RPC and HTTP+JSON:

| Method | Purpose |
| - | - |
| `GetContexts` | List the authenticated caller's visible contexts by latest activity. |
| `GetContext` | Retrieve one visible context with its messages, artifacts, and latest status. |
| `DeleteContext` | Remove the caller's access; the last recorded caller triggers cancellation and graph deletion. |

All three methods belong to the same extension and use the same canonical URI. An Aion-served
agent card declares the extension once.

HTTP+JSON paths below are relative to the addressed agent or distribution's A2A endpoint.

## Agent Card Declaration

<Note>
  This unified contract is provided by Aion control-plane endpoints. The Python SDK's standard agent server does not
  advertise this extension or implement its summaries and `DeleteContext` lifecycle. Its internal, non-advertised
  [GetContext](/a2a/extensions/aion/context/get-context/1.0.0) and
  [GetContexts](/a2a/extensions/aion/context/get-contexts/1.0.0) helpers have a separate read-only contract.
  A server should declare the unified URI only when it implements the contract documented here.
</Note>

```json theme={null}
{
  "capabilities": {
    "extensions": [
      {
        "uri": "https://docs.aion.to/a2a/extensions/aion/context/1.0.0",
        "description": "List, retrieve, and delete caller-visible conversation contexts.",
        "required": false
      }
    ]
  }
}
```

## Activation

This extension is declarative. It will always be active and does not require activation.

Clients do not need to send the URI in `A2A-Extensions` or `a2a-extensions`. When a client does
send it, the server preserves it as ordinary request extension metadata.

## Authentication and Isolation

Contexts belong to the receiving AgentIdentity within the addressed edge agent environment. Separate
bindings associate admitted callers by exact principal identifier and type. Ordinary caller reads use
those bindings and return the complete visible context history, including other admitted participants.
Knowing a `contextId` or belonging to the same organization is not authorization to join it.

Verified provider participants can share a provider conversation. Account and guest clients cannot
join an occupied private context simply by supplying its ID. New roots receive a private downstream
identifier instead of blindly forwarding an untrusted caller-provided string.

A verified anonymous-session bearer identifies one guest and can authorize its bound contexts on
public A2A endpoints. A bare shared anonymous principal cannot. Session access does not make a
private distribution or the authenticated GraphQL catalog public. See
[Caller Authentication](/sdk/python/extensibility/caller-authentication) for creation, renewal, and token boundaries.

Binding writes are best effort and do not delay message forwarding. Failed writes can leave history
unavailable until a later authorized message repairs access; there is no guaranteed durable retry.
Provider room departures and membership revocations are not yet synchronized. An explicitly
authorized receiving-agent history request is distinct from ordinary caller access; it does not
allow every caller to read all conversations owned by that agent.

## GetContexts

`GetContexts` returns lightweight caller-visible conversations from most to
least recent.

### JSON-RPC Request

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "list-contexts-1",
  "method": "GetContexts",
  "params": {
    "historyLength": 50,
    "historyOffset": 0
  }
}
```

`params` may be omitted to use the defaults.

| Field | Type | Required | Description |
| - | - | - | - |
| `historyLength` | `Integer` | optional | Contexts to return. Defaults to `50`; maximum `100`. |
| `historyOffset` | `Integer` | optional | Newest contexts to skip. Defaults to `0`. |
| `metadata` | `Object` | optional | Request metadata. |

### JSON-RPC Success

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "list-contexts-1",
  "result": [
    {
      "contextId": "conversation-123",
      "title": "Reno weather forecast",
      "summary": "The caller requested the current weather in Reno. The agent returned a forecast and temperature.",
      "lastActivityAt": "2026-09-10T18:42:11.532Z"
    },
    {
      "contextId": "conversation-456",
      "title": null,
      "summary": null,
      "lastActivityAt": "2026-09-09T09:15:04.107Z"
    }
  ]
}
```

The `result` is a raw array rather than an object wrapper.

| Field | Type | Description |
| - | - | - |
| `contextId` | `String` | Opaque caller-visible context identifier. |
| `title` | `String \| null` | Generated current subject, when available and enabled by organization policy. |
| `summary` | `String \| null` | Generated conversation summary, when available and enabled by organization policy. |
| `lastActivityAt` | RFC 3339 timestamp | Latest visible-context task activity, reported in UTC. |

`lastActivityAt` uses the latest persisted task update. If an admitted edge task does not yet
have a local task projection, its creation time is used.

### HTTP+JSON Binding

```http theme={null}
POST /contexts:get
Content-Type: application/json
Authorization: Bearer <aion-token>
```

The request body uses the same parameter object. The response body is the same raw summary array.

## GetContext

`GetContext` returns one caller-visible context. History is chronological; pagination selects a
newest-relative slice before the server returns it in chronological order.

### JSON-RPC Request

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "get-context-1",
  "method": "GetContext",
  "params": {
    "contextId": "conversation-123",
    "historyLength": 10,
    "historyOffset": 0
  }
}
```

| Field | Type | Required | Description |
| - | - | - | - |
| `contextId` | `String` | required | Non-blank caller-visible context identifier. |
| `historyLength` | `Integer` | optional | History messages to return. Defaults to `50`; maximum `100`. |
| `historyOffset` | `Integer` | optional | Newest history messages to skip. Defaults to `0`. |
| `metadata` | `Object` | optional | Request metadata. |

### JSON-RPC Success

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "get-context-1",
  "result": {
    "contextId": "conversation-123",
    "title": "Reno weather forecast",
    "summary": "The caller requested the current weather in Reno. The agent returned a forecast and temperature.",
    "history": [
      {
        "messageId": "msg-1",
        "role": "ROLE_USER",
        "parts": [
          {
            "text": "What's the weather like in Reno today?"
          }
        ]
      },
      {
        "messageId": "msg-2",
        "role": "ROLE_AGENT",
        "parts": [
          {
            "text": "The weather in Reno is 72 degrees Fahrenheit."
          }
        ]
      }
    ],
    "artifacts": [],
    "status": {
      "state": "TASK_STATE_COMPLETED"
    },
    "lastActivityAt": "2026-09-10T18:42:11.532Z"
  }
}
```

| Field | Type | Description |
| - | - | - |
| `contextId` | `String` | Caller-visible context identifier. |
| `title` | `String \| null` | Generated current subject, when available and enabled by organization policy. |
| `summary` | `String \| null` | Generated conversation summary, when available and enabled by organization policy. |
| `history` | `Message[]` | Chronological A2A messages in the selected history page. |
| `artifacts` | `ContextArtifact[]` | Up to 50 latest durable artifacts, newest first, each qualified by task. |
| `status` | `TaskStatus` | Latest visible-context task status. |
| `lastActivityAt` | RFC 3339 timestamp | Latest visible-context task activity, reported in UTC. |

The result combines messages across the context's tasks; it is not an array of complete tasks.
Artifact selection is independent of message pagination. Each artifact has the usual A2A artifact
fields plus `taskId`, the caller-facing task identifier:

```json theme={null}
{
  "taskId": "task-123",
  "artifactId": "report",
  "name": "Weather report",
  "parts": [{ "text": "The weather in Reno is 72 degrees Fahrenheit." }]
}
```

Artifact identity is the pair `(taskId, artifactId)`. Two tasks can both return an artifact named
`report`. Aion selects at most 50 artifacts before loading their parts, orders them by latest update
with a stable row-id tie break, and excludes `aion:thinking-delta` and `aion:stream-delta`. This is a
recent-artifact window, not an exhaustive artifact export or a bound on individual artifact bytes.

If the caller has no visible projection for `contextId`, the server returns `ContextNotFound`
(code `1000`, HTTP `404`) without revealing whether another caller uses that identifier.

### HTTP+JSON Binding

```http theme={null}
POST /context:get
Content-Type: application/json
Authorization: Bearer <aion-token>
```

The request and response bodies use the same parameter and result objects shown above.

## Generated Context Summaries

`title` and `summary` are optional generated metadata. They are nullable because generation is
best effort and controlled by the organization that owns the addressed agent. When that
organization disables conversational summarization, both fields are returned as `null` even if a
previously generated value remains stored.

Generation may send bounded conversation text to an external model service. Organizations that
must keep conversational information within their own network should leave conversational
summarization disabled. Clients must not assume that generated values exist or that they include
the newest task.

Aion first attempts generation after the caller's first completed task, then after each additional
ten-task checkpoint. The title reflects the latest summarized task window. The summary combines
the previous generated summary with that bounded window, so the full conversation does not need to
be sent again as the context grows.

Generation and catch-up are asynchronous. A failed attempt leaves the previous values unchanged,
and a later terminal task can cause Aion to catch up one checkpoint at a time. Context reads never
wait for this work.

## DeleteContext

`DeleteContext` first removes the requesting caller's binding. If other recorded bindings remain,
it returns success without canceling tasks or deleting the graph. The receiving-agent owner field
is not itself a binding; a genuine agent self-call can have a binding like any other caller.

When the last recorded binding is removed, Aion records a durable `DELETING` state, which prevents
new task admission. Existing tasks can still publish
observations so cancellation and completion can settle. Final deletion prevents subsequent payload
projection from recreating the retired history. Cancellation uses the ordinary A2A task-control path.

Cancellation proceeds in bounded groups and checks task state when the outcome is uncertain.
For last-binding deletion, success is returned only after all tasks are terminal and the graph-deletion transaction
commits. A task may also complete naturally while cancellation is being attempted.

Terminal states are:

* `TASK_STATE_COMPLETED`
* `TASK_STATE_FAILED`
* `TASK_STATE_CANCELLED`
* `TASK_STATE_REJECTED`

### JSON-RPC Request

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "delete-context-1",
  "method": "DeleteContext",
  "params": {
    "contextId": "conversation-123"
  }
}
```

| Field | Type | Required | Description |
| - | - | - | - |
| `contextId` | `String` | required | Non-blank caller-visible context identifier. |
| `metadata` | `Object` | optional | Request metadata. |

### JSON-RPC Success

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "delete-context-1",
  "result": {
    "contextId": "conversation-123"
  }
}
```

Deletion is idempotent. The server returns the same success for a context that is already absent or
not visible to the caller. This avoids disclosing another caller's context.

### Deletion In Progress

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "delete-context-1",
  "error": {
    "code": 1001,
    "message": "Context deletion is in progress",
    "data": {
      "contextId": "conversation-123",
      "retryable": true,
      "deletionOperationId": "b92fe461-b3e8-4b89-a736-573154338f23"
    }
  }
}
```

An outstanding cancellation, transient failure, or request timeout does not imply deletion success
or permanent failure. Once deletion is durable, Aion keeps the context fenced, returns this
retryable result, and can recover the operation after a restart. Retry `DeleteContext` with the
same caller and context id; do not create a replacement task in that context while it is deleting.
`deletionOperationId` is optional diagnostic metadata, not an additional request parameter.

If cancellation is definitively refused, Aion drains the outstanding attempts before restoring the
context to `ACTIVE` and returning non-retryable `ContextNotDeletable` (code `1002`). Work already
canceled is not restarted or rolled back. An active task alone is not a definitive refusal.
The removed caller binding is not silently restored; stale grant retries cannot re-admit it.

### HTTP+JSON Binding

```http theme={null}
POST /context:delete
Content-Type: application/json
Authorization: Bearer <aion-token>
```

The request body is the `DeleteContext` parameter object. The success body is
`{"contextId":"conversation-123"}`. Lifecycle conflicts use HTTP `409 Conflict` problem details,
with the same context id, retryability, and optional deletion-operation id as JSON-RPC.

## Deletion Scope

Only last-binding finalization soft-deletes the receiving-agent edge context, its bindings, edge-task mappings, linked
local native and projected tasks, messages, artifacts, parts, callback routes, and owned push
notification configurations. Task traces and referenced Files are not soft-deleted by this action.
It does not:

* remove another caller's recorded binding through an ordinary caller-delete request;
* send a context-deletion command to a remote agent;
* claim that a remote agent erased its own conversation memory; or
* prevent a later request from reusing the same `contextId`.

Clients should treat success as confirmation that the caller's current Aion history is no longer
available through `GetContexts` or `GetContext`.

If another recorded binding remains, the context still exists and a private caller cannot rejoin
merely by sending its ID. After actual graph deletion, a later send using that caller-facing ID
creates a new mapping with a fresh downstream identifier, not a continuation of the retired graph.

Because grant recording is best effort, an unrecorded participant may still be using a context when
the last recorded binding is removed. The graph can then be deleted. This accepted limitation is
not a guarantee that every currently active participant appears in the binding table.

### Retention And Files

Background retention removes complete context graphs, not individual expired task siblings. For an
active context, recent activity or nonterminal work in any linked task protects the whole graph.
An explicitly deleted context instead ages from its deletion timestamp.

Each eligible context is rechecked and physically purged in its own transaction, including payload
children, callback routes, task traces, task roots, and the context mapping. This removes Aion's
stored native and downstream-projection history, not an external server's retained data.

After that commit, Aion requests best-effort deletion of locally managed Files owned by the graph's
organization. A surviving reference, including one in another soft-deleted context, preserves the
File. Remote and cross-organization File references do not authorize automatic deletion. File
storage billing continues until the File service performs its normal lifecycle deletion; hiding
conversation history alone does not stop File billing.

## Errors

| Condition | JSON-RPC code | HTTP status | Lifecycle retryable |
| - | - | - | - |
| Missing authentication | `-32010` | `401 Unauthorized` | Not supplied |
| Blank `contextId` or invalid pagination | `-32602` | `400 Bad Request` | Not supplied |
| Context is not visible during `GetContext` | `1000` | `404 Not Found` | `false` |
| Durable deletion remains in progress | `1001` | `409 Conflict` | `true` |
| Definitive cancellation refusal prevents deletion | `1002` | `409 Conflict` | `false` |

Context lifecycle errors carry sanitized `contextId` and `retryable` fields in JSON-RPC `error.data`.
The HTTP+JSON binding exposes them as problem-detail extensions. Its problem `type` is the canonical
Context extension URI followed by `#context-not-found`, `#context-deletion-in-progress`, or
`#context-not-deletable`, respectively. Provider error payloads and internal row identifiers are not
included.

Error objects otherwise follow the
[JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification).
