> ## 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.

# Conversation History

> Read the tasks and artifact versions of the conversation the current turn belongs to.

`aion.core.agent.conversation` reads what the conversation of the current turn already holds: its tasks, the
versions of its artifacts and the generation of its id. It is the counterpart of `emit_*`, which write what a
turn says. It lives in `aion.core`, so a LangGraph graph, an ADK agent and an executable extension use it alike.

```python theme={null}
from aion.core.agent import conversation
```

The functions take no context argument. `aion serve` installs the history of every turn it runs on the turn's
[`AionRuntimeContext`](https://docs.aion.to/sdk/python/messaging/runtime-context), and the functions read it from there. Outside a
turn - in a unit test, or in code that runs before the server starts the turn - they raise
`ConversationUnavailableError`.

## Who sees what

A turn reads the context of its task as the caller that started the turn was admitted into it:

* in a private conversation - an anonymous session, the application's own user - it reads that caller's tasks;
* in a conversation Aion routes through its gateway, it reads every participant's tasks, whoever started them;
* it never reads another context, and a context that is being deleted reads as empty.

Every read goes to the task store, so every instance of the agent answers from the same data. What the turn has
emitted but the server has not saved yet is not there.

## Tasks

```python theme={null}
task = await conversation.current_task()
earlier = await conversation.get_task(task_id)
every_task = await conversation.tasks()
waiting = await conversation.tasks(unfinished=True)
```

| Function | Returns |
| - | - |
| `current_task()` | The turn's own task as the store holds it, or `None` before it is first saved. |
| `get_task(task_id)` | A task of this conversation with its history and artifacts; `None` for any other task. |
| `tasks(unfinished=False)` | The tasks, oldest first; with `unfinished=True`, those without an outcome yet. |

Tasks are `a2a.types.Task` objects.

## Artifact versions

The same `artifact_id` written by several tasks of a conversation is one artifact in several versions, numbered
from `0` in the artifact's `metadata["version"]`.

```python theme={null}
spec = await conversation.find_artifact("evolution-spec")
if spec is not None:
    text = "".join(part.text for part in spec.artifact.parts)
    print(spec.version, spec.task_id)

history = await conversation.artifact_versions("evolution-spec")
```

| Function | Returns |
| - | - |
| `find_artifact(artifact_id)` | The latest version - the one the newest task wrote - or `None`. |
| `artifact_versions(artifact_id)` | Every version, newest task first. |
| `artifact_version_to_write(artifact_id)` | The number the current task writes the artifact under. |
| `stamp_artifact_version(event)` | Writes that number into a `TaskArtifactUpdateEvent` before it is emitted. |

A version is an `ArtifactVersion` with `task_id`, `artifact` (an `a2a.types.Artifact`), `version` and
`updated_at`.

A task keeps the number it took: chunks and replacements of the artifact, and the artifact in a later turn of the
same task, carry the same number. Two tasks of one conversation that write the same artifact at the same time can
take the same number.

## Generation

```python theme={null}
marker = await conversation.generation()
```

An opaque marker of this use of the conversation's id. It changes when a deleted conversation's id is taken
again, so state you keep outside the server under the conversation's id - a branch, a file - can tell an earlier
conversation from the current one. Compare it; do not parse it.

## Binding the history

`conversation.history()` returns the current turn's history object. Its methods are the functions above, bound to
this turn, so you can hand one to code that runs later in the turn:

```python theme={null}
history = conversation.history()
lookup = history.find_artifact
```

The history does not include the conversation's messages. To read earlier turns, use your framework's own state:
the LangGraph checkpoint or the ADK session.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.