Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_framework_hosting-1.0.0a260730.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file agent_framework_hosting-1.0.0a260730.tar.gz.

File metadata

  • Download URL: agent_framework_hosting-1.0.0a260730.tar.gz
  • Upload date:
  • Size: 7.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agent_framework_hosting-1.0.0a260730.tar.gz
Algorithm Hash digest
SHA256 38f2520d740b529a8f5a74b0c398856a0fe494d71c8abebb80f8b53025945b29
MD5 bbfe26a1a1508fa0faa434292097b407
BLAKE2b-256 725a15bcd728f4d560b5e351ced3156c313a420678b34cbd8266c9ff28a846a5

See more details on using hashes here.

File details

Details for the file agent_framework_hosting-1.0.0a260730-py3-none-any.whl.

File metadata

  • Download URL: agent_framework_hosting-1.0.0a260730-py3-none-any.whl
  • Upload date:
  • Size: 8.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agent_framework_hosting-1.0.0a260730-py3-none-any.whl
Algorithm Hash digest
SHA256 ffd827ade397f3c2b67b69d53c983ab0107f06c40576fb262d2aa06879161566
MD5 c32fbbc56c7fcbdc93e8bc34cc05ef80
BLAKE2b-256 bbb7237a29d7d22deeab101cb6639e209a65e82d69218fae448e073496ea3248

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page