Skip to main content
Agents use in-memory conversation history unless you provide a manager. A thread groups related runs; a run contains the user turn, model/tool messages, and execution state produced while answering it.

Configure file-backed history

With model configured:
Close the history after all agents and requests using it finish. Agents do not close caller-owned resources. File persistence is for a process that owns its storage directory; it is not a substitute for a shared database across independent workers.

Continue a thread

Send each new turn with the same namespace and ThreadID. You do not need to resend previous messages: the history manager loads them. Omitting PreviousRunID follows the thread’s current history; setting it chooses the earlier run from which to continue. Use a paused result’s run ID when explicitly resuming that branch. Choose thread IDs in your application before invoking the agent. A new ID starts another thread. Reusing a run ID is not a general HTTP idempotency mechanism: saves append increments to a run, and side effects need their own idempotency design.

Read a transcript

Model context can be summarized or filtered. For a user-visible transcript, use history.LoadTranscript, or the paginated API, rather than treating the model’s current message list as the full conversation. With manager as your *history.CommonConversationManager:
Pages contain complete stored turns in chronological order. Set BeforeRunID to NextBeforeRunID to fetch the next older page. An empty next value means the start of history. Latest carries the current thread state even when reading an older page.

Supply database persistence

Implement history.ConversationPersistenceAdapter, then construct history.NewConversationManager(adapter). It owns ID/time generation, message loading/saving, and summary persistence. Without native pagination, the helper loads a transcript and slices it in memory. Database implementations should use a bounded query ordered by insertion, not lexical run ID. Enforce namespace boundaries and run-ID uniqueness atomically in storage. Persist metadata and tool state as well as message text; approval and continuation depend on them.

Message attribution

The incoming history.Message bundle can carry sender information. history.WithMessageAttribution() enables attribution prefixes when producing model context. Steering notices are enabled by default for messages delivered while a run is active; WithoutSteeringNotices() disables that annotation. Neither option replaces application authentication.

Groups, parents, and visibility

Input.GroupID assigns a new conversation to a group; empty means default. ParentThreadID identifies the thread that spawned it, and Hidden marks an internal thread. Continuations and forks preserve stored attributes. Sub-agent threads are hidden, parented to the caller, and normally grouped under its thread ID. Routine occurrences use the routine ID as their group. ThreadLister.ListThreads(ctx, namespace, groupID) returns thread metadata, including these attributes. AG-UI omits hidden threads unless include_hidden=true; this visibility flag is a presentation filter, not an authorization boundary. Custom persistence implements the current save signature:
Assign attributes on creation and preserve them on incremental saves, continuations, and forks. Append supplied messages to an existing run; replace non-nil metadata even when there are no new messages. Preserve its thread, conversation, and creation time. This incremental contract supports opening-turn persistence and later state transitions.

Message timestamps

Each history.Message bundle carries CreatedAt. Built-in timestamp middleware records model and tool completion time inside their execution boundary. Other bundles receive the run clock’s time when accepted. Old stored bundles can have a zero timestamp. Hydrated AG-UI user, assistant, and tool messages expose metadata.createdAt as RFC 3339 or null for older untimed messages. metadata.senderId carries the bundle sender when known. The embedded chat displays message and tool-result times; these are distinct from the run’s timestamps.