Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Agent

agent conversation memory (using Osyrin.Agents)

using Osyrin.Agents;

A conversation is stored as a `ChatSession` plus its `ChatMessage` turns, so an agent asked a follow-up can refer back to what was said earlier. Both ride `Osyrin.Agents` — the same capability an agent declaration already needs — so there is nothing extra to opt into. An agent stays stateless until a call names a conversation. A conversation belongs to the user who started it and is readable only by them.

preview1 example compiled by CIagentchatmemorycapability

Summary#

An agent is stateless by default. Each turn is answered on its own: nothing from the previous exchange is in scope unless a call names the conversation it belongs to. That is the right shape for an agent that classifies a document or answers one question.

A conversation is stored as a ChatSession with its turns as ChatMessage rows, and an agent asked a follow-up can see what came before. Both entities ride Osyrin.Agents — the capability an agent declaration already requires — so a conversation needs no second import.

using Osyrin.Agents;

Signature#

using Osyrin.Agents;

Two entities enter the app's model:

entitywhat it holds
ChatSessionone conversation — which agent, its title, when it was last active, who it belongs to, and optionally the record it is about
ChatMessageone turn — a user message, an assistant reply, a tool call or a tool result, in Sequence order

Description#

Conversations are part of what the agent surface is. They are not a second thing to import: a session and its turns are what an agent that holds a conversation, parks for a human, or reports an outcome would otherwise re-implement, so they ride Osyrin.Agents itself. Nothing about your agents changes to get them: the same agent declaration, the same calls.

Which conversation, if any, is decided per call. A request that carries a conversationId continues that conversation; one that does not starts a new one. An app whose agents only ever classify a document names no conversation and its tables stay empty.

A conversation belongs to one user. It is stamped with the user who created it, listings return only that user's conversations, and asking for someone else's by id answers 404 — the same answer as an id that does not exist, so no one can probe for which conversations exist. Anonymous visitors own no conversations: an anonymous caller gets an empty list, and creating one requires a signed-in user.

A long conversation is summarised rather than truncated. When the history outgrows the model's context window, earlier turns are replaced by a summary turn, so the beginning of the conversation is still represented instead of being dropped.

Entity context is optional. A conversation can record the record it is about — "ask the agent about this order" — so it can be listed alongside that record rather than in one undifferentiated pile.

Examples#

An app whose agent holds a conversation:

using Osyrin.Agents;

[Principal] entity User {
  [MaxLength(255)] string Email;
}

entity Order {
  [Required, MaxLength(50)] string Reference;
}

A chat request that carries a conversationId continues that conversation; one that does not starts a new one.

See also#

Related

default LLM model (app.DefaultModel)

Declares the app's default LLM — the provider, model, API-key secret, and optional endpoint — as a single app-level…