Principle:Microsoft Agent framework Durable Agent State Persistence
| Knowledge Sources | |
|---|---|
| Domains | Durable_Agents, State_Management, Serialization |
| Last Updated | 2026-02-11 17:00 GMT |
Overview
Principle of defining a versioned, cross-platform schema for persisting agent conversation state, enabling durable agent sessions that survive process restarts and work across language implementations.
Description
Durable Agent State Persistence solves the problem of maintaining agent conversation context across restarts, failures, and language boundaries. Without a formal schema, each implementation would serialize state differently, breaking interoperability between .NET and Python agents.
This principle mandates:
- Versioned schema: Every state payload includes a schemaVersion field (semver), enabling forward/backward compatibility and migration.
- Discriminated content types: Message content uses a $type discriminator field to distinguish between text, data, error, function calls, function results, hosted files, vector stores, reasoning, URIs, and usage statistics.
- Structured conversation history: Messages are grouped into conversation entries (requests and responses) with timestamps and optional correlation IDs.
- Usage tracking: Token usage statistics (input, output, total) are embedded in responses for cost monitoring.
Usage
Apply this principle when implementing agent state persistence for durable agents, particularly in scenarios involving Azure Functions, Durable Task Framework, or any stateful agent hosting where conversation state must survive beyond a single process lifetime.
Theoretical Basis
The schema follows the discriminated union pattern for extensible content types:
Pseudo-code Logic:
# Abstract state persistence pattern (NOT real implementation)
@dataclass
class DurableAgentState:
schema_version: str # semver, e.g., "1.0.0"
data: AgentData
@dataclass
class AgentData:
conversation_history: list[ConversationEntry]
@dataclass
class ConversationEntry:
created_at: datetime
correlation_id: str | None
messages: list[ChatMessage]
@dataclass
class ChatMessage:
role: Literal["user", "assistant", "system", "tool"]
contents: list[ContentItem] # Discriminated by $type field
# Content types discriminated by $type:
# "text" -> TextContent
# "functionCall" -> FunctionCallContent
# "functionResult" -> FunctionResultContent
# "error" -> ErrorContent
# etc.
Key properties:
- Schema versioning: Enables non-breaking evolution of the state format
- Discriminated unions: The $type field allows deserializers to select the correct content type without ambiguity
- Cross-language interop: JSON Schema serves as a language-neutral contract