Configure file-backed history
Withmodel configured:
Continue a thread
Send each new turn with the same namespace andThreadID. 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, usehistory.LoadTranscript, or the paginated API, rather than treating the model’s current message list as the full conversation.
With manager as your *history.CommonConversationManager:
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
Implementhistory.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 incominghistory.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:
Message timestamps
Eachhistory.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.