Skip to main content

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
}
  • SystemPrompt is the standing application instruction.
  • Summary is the active compaction summary, empty until one exists. On every provider request, a non-empty Summary is projected as one user message before Messages.
  • Messages contains 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: Final is zero and NewMessages is empty. A completed compaction remains in the returned Context and Compactions.
  • 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 in Final. An attempt ending in error or abort is not added to Context.Messages, while a later overflow retry can replace it as Final.
  • 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.

API reference