Files
Giles Odigwe e39a8a2e79
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
Python: Bump Python package versions for 1.13.0 release (#7443)
* Bump Python package versions for 1.13.0 release

Bump all 37 Python package projects because the CHANGELOG-driven release includes cross-package feature-usage telemetry, with core and root advancing to 1.13.0, OpenAI to 1.12.0, patch bumps for other stable packages, and 260730 stamps for alpha and beta packages. No optional beta cohort bump was applied; every prerelease package changed. Raise core floors conservatively across co-released packages.

Copilot-Session: e234a28b-c2fd-4ff4-a51d-3d8917936541

* Align co-released Python package dependencies

Update the four hosting adapter pins to the co-released agent-framework-hosting alpha and raise the Azure Functions Durable Task floor to the co-released beta.

Copilot-Session: e234a28b-c2fd-4ff4-a51d-3d8917936541

* Minimize Python release lockfile updates

Regenerate uv.lock with the pre-commit hook pinned uv version so the release changes only workspace package versions while preserving platform markers and agentlightning 0.3.0.

Copilot-Session: e234a28b-c2fd-4ff4-a51d-3d8917936541

---------

Copilot-Session: e234a28b-c2fd-4ff4-a51d-3d8917936541
2026-07-30 22:47:07 +00:00
..

agent-framework-hosting

Shared execution-state helpers for app-owned Agent Framework hosting.

This package keeps Agent Framework state separate from web-framework concerns:

  • AgentState — pairs an agent target with a core SessionStore (session_id -> AgentSession).
  • WorkflowState — resolves a workflow target, including direct Workflow instances, workflow factories, WorkflowBuilder, and orchestration builders.

The experimental SessionStore and FileSessionStore implementations live in agent-framework-core and are imported from agent_framework. SessionStore provides get/set/delete by an app-selected id. Each successful get returns an independent copy, so a run works from a snapshot instead of mutating an older continuation point in place. The store does not know how to create a new value for an id it hasn't seen before — use AgentState.get_or_create_session(...) for that, since only the state object has both the store and the resolved target. Workflow checkpointing should use the existing CheckpointStorage abstraction directly; if an app needs per-session resume, keep a small app-owned cursor such as session_id -> checkpoint_id.

SessionStore accepts opaque non-empty IDs so custom database and Redis implementations can use their native key contracts. FileSessionStore limits its direct keys to 128 ASCII letters, digits, -, and _. AgentState passes the app-selected ID to the configured store unchanged; each store implementation owns any validation or normalization required by its backend. This does not replace parameterized queries or backend-specific validation in custom stores.

FileSessionStore uses msgspec JSON. Register custom objects placed in AgentSession.state explicitly before sessions are saved or restored:

from agent_framework import register_state_type


class MyState:
    ...


# Register at module import time, before any provider instance is created.
register_state_type(MyState, type_id="my_state")

Classes with to_dict() / from_dict() methods and explicitly registered Pydantic models receive default codecs. Other classes can provide encoder= and decoder= callbacks. Keep registration at module level so importing the module prepares cold-start session restoration before its context provider is instantiated. Unregistered Pydantic models still use legacy same-process auto-registration for now, but emit DeprecationWarning; cold-start deserialization is not guaranteed on that path.

JSON is the default file format. Use MessagePack for a compact binary file:

store = FileSessionStore("storage/sessions", serialization_format="msgpack")

Use FastAPI, Starlette, Azure Functions, Django, or another framework for route registration, auth, middleware, response construction, and background work.

The core SessionStore is an in-memory dict with no eviction — every id ever stored stays resolvable for the life of the process. That is intentional: protocols such as OpenAI Responses' previous_response_id are designed to let a caller continue from any earlier point in a conversation, not just the latest turn, so every id handed out needs to stay independently resolvable. If you back the store with real storage (Redis, a database, ...), you are responsible for that store's own TTL/eviction policy; this in-memory reference implementation does not model that concern.

Quickstart

from agent_framework import FileSessionStore
from agent_framework.openai import OpenAIChatClient
from agent_framework_hosting import AgentState

agent = OpenAIChatClient().as_agent(name="Assistant")
state = AgentState(agent, session_store=FileSessionStore("storage/sessions"))
session = await state.get_or_create_session("conversation-1")
result = await (await state.get_target()).run("Hello", session=session)

If a protocol mints a new continuation id on every response, store the session explicitly after run(...) returns. run(...) may update the session, so store the post-run object:

session = await state.get_or_create_session(previous_response_id)
result = await (await state.get_target()).run("Hello", session=session)
await state.set_session(response_id, session)

This response-keyed pattern supports simultaneous branches: callers may read the same previous_response_id, receive independent working copies, and store each result under a different new response id. A stable conversation_id is different: explicitly write the completed session back under that same id to advance its mutable head, and ensure only one caller advances it at a time. AgentState does not provide that application-level locking or optimistic concurrency control.

Targets can be direct instances, synchronous factories, asynchronous factories, or awaitables:

state = AgentState(create_agent)  # cached by default
state = AgentState(create_agent, cache_target=False)

WorkflowState mirrors this shape for workflow targets:

from agent_framework import InMemoryCheckpointStorage
from agent_framework_hosting import WorkflowState

state = WorkflowState(create_workflow)
storage = InMemoryCheckpointStorage()
result = await (await state.get_target()).run("Hello", checkpoint_storage=storage)
latest = await storage.get_latest(workflow_name=(await state.get_target()).name)

A Workflow instance allows only one active run. Hosts that need simultaneous workflow runs should pass a factory or builder and set cache_target=False so each request receives a fresh workflow instance.

WorkflowState also accepts an unbuilt workflow builder directly:

from agent_framework import WorkflowBuilder
from agent_framework_hosting import WorkflowState

builder = WorkflowBuilder(start_executor=executor)
state = WorkflowState(builder)  # calls builder.build() when the target is resolved

This is structural: orchestration builders from agent_framework_orchestrations (SequentialBuilder, ConcurrentBuilder, HandoffBuilder, GroupChatBuilder, and MagenticBuilder) also work because they expose the same zero-argument build() -> Workflow method.

Cross-channel identity linking, multicast delivery, background runs, continuation tokens, and durable delivery runners are follow-up enhancements, not part of this v1 state surface.