Storing and continuing conversation state
Golato retains nothing between calls. A run returns agent.Result, the host application stores result.Context, and
the next run receives it again. That single loop is the whole persistence model.
stored Context + new prompts
→ Agent run
→ Result.Context
→ replace stored state
Describing Context state
type Context struct {
SystemPrompt string
Summary compaction.Summary
Messages []message.Message
}
SystemPromptis the standing application instruction.Summaryis the active compaction summary, empty until one exists. On every provider request, a non-emptySummaryis projected as one user message beforeMessages.Messagescontains the replayable messages after that summary.
The Agent copies the input before starting and returns a new copy. It never mutates the caller's context.
Only Result.Context is continuation state. NewMessages, Final, and Compactions are run records that an
application may store separately for display, audit, or metrics.
Continuing a conversation
The application replaces its stored snapshot with the returned Context on success. On failure, it keeps or discards
the returned context according to the external side effects it observed, because a tool may already have changed files
or another system.
state := agent.Context{SystemPrompt: "You are a concise assistant."}
first, err := assistant.Run(ctx, agent.Input{
Context: state,
Prompts: []message.UserMessage{message.NewUserMessage("What is nvim?")},
})
if err != nil {
return err
}
state = first.Context
second, err := assistant.Run(ctx, agent.Input{
Context: state,
Prompts: []message.UserMessage{message.NewUserMessage("How does it differ from vim?")},
})
if err != nil {
return err
}
state = second.Context
The second question never names nvim, so “it” can only resolve through the stored context from the first round. If the
second answer explains how nvim differs from vim, the conversation carried over. Without the stored state, nothing
would tie “it” to nvim.
Final and NewMessages need no manual append, because replay-safe values are already reflected in the returned state.
One Agent can serve many independent contexts. If two runs use the same stored context concurrently, they produce two successors. Writes are serialized or stale versions rejected when saving, so an older result cannot overwrite a newer one.
Separating continuation from a transcript
Compaction removes old raw messages from Context.Messages and folds them into Summary. If the application needs an
append-only transcript, store that as a separate record.
Serializing messages explicitly
message.Message is an interface over concrete value types with no built-in codec. The application stores a type tag
for every message and content block, and reconstructs the values on read. The exact shape is its choice.
{
"system_prompt": "You are concise.",
"summary": "",
"messages": [
{ "type": "user", "content": [{ "type": "text", "text": "Hello" }] },
{ "type": "assistant", "content": [{ "type": "text", "text": "Hi" }] }
]
}
Dropping a fact changes what the next provider request sees, so the stored record keeps image bytes or URLs, assistant metadata needed for replay, tool call IDs and names, raw arguments, matching tool results, and thinking signatures.
Handling failed and canceled runs
A failed run still returns a result, and the point where it ends controls what can be replayed.
- Before prompt admission:
Finalis zero andNewMessagesis empty. A completed compaction remains in the returnedContextandCompactions. - After prompt admission: the prompts are in the returned context, unless a later successful compaction covers them.
- Assistant attempts: every attempt appears in
NewMessages. Only the last attempt appears inFinal. An attempt ending in error or abort is not added toContext.Messages, while a later overflow retry can replace it asFinal. - Tool batch failure: a replayable assistant attempt and any tool results recorded before the failure remain in
Context.Messages. - Tool side effects: a tool may have changed external state before cancellation or failure. Decide whether to keep the returned state and continue without resubmitting, or discard it and retry from the prior state.