Skip to content

Sessions

Every request is independent by default, which keeps results reproducible and fallback safe. A conversation is the case where that default wastes work: the provider often already has everything the next turn needs. A session is how a caller says these requests belong together, without having to know what any particular provider does about it.

with client.session("copilot:auto") as chat:
    client.generate("Summarize this report.", session=chat)
    client.generate("Now list the risks.", session=chat)

What Each Provider Actually Saves

The providers that can carry state between turns save completely different things, which is why the handle is opaque rather than a conversation object:

Provider What an open session keeps What that saves
GitHub Copilot The conversation, server-side Prior turns are not re-sent at all: fewer tokens billed, and no duplicated history
llama.cpp The supervised server, pinned No model load between turns, and the KV cache the next turn reuses survives
Ollama The model, resident (keep_alive) No reload of several gigabytes of weights mid-conversation

Everything else treats a session as inert.

A Session Never Changes an Answer

It is a performance and cost optimization, and holding that line is what makes it safe to pass one everywhere. Opening a session against a provider that cannot keep state is allowed and does nothing:

session = client.session("openai:gpt-5")
session.supported  # False
session.reuse  # 'unsupported', and every request behaves exactly as it would have

Reuse Is Reported, Not Assumed

reuse says what happened on the last turn, not what was hoped for:

Value Meaning
fresh The provider started new state: the first turn, or one it had already expired.
resumed The provider continued state it already held.
unsupported Nothing was reused: this provider cannot, or that turn went somewhere else.

State Is Bound to One Target

Provider state is not portable, so a session names the target it belongs to and applies only there. If a route falls back to a different provider, or a different model on the same one, that turn simply runs without it and reports unsupported:

result = client.generate(
    "and the risks?",
    route=ai.Route(targets=("ollama:qwen3:8b", "openai:gpt-5")),
    session=chat,  # chat belongs to ollama:qwen3:8b
)
chat.reuse  # 'unsupported' if the fallback answered

Because a session already names a target, a caller can leave the target off entirely and it stands in; it never overrides an explicit target or route.

Closing Is Local

close() stops the handle being used; it does not reach out to the provider. Server-side state expires on the provider's own schedule (Ollama's keep_alive timer, Copilot's service-side session lifetime). Closing the client itself does release what an adapter holds open locally, such as a Copilot SDK session.

Key Takeaways

  • A session is an opaque handle, not a conversation: the library never interprets what a provider stores in it.
  • It never changes an answer, so passing one to a stateless provider is safe and inert.
  • reuse reports what the provider actually did, including when a fallback meant the session did not apply.

See Also