Files
microsoft--agent-framework/python/packages/hosting/README.md
Eduard van Valkenburg f2d02e58b3 Python: Add hosting core and Responses channel (#6580)
* Add Python hosting core and Responses channel

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address hosting core review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Adopt source pyright typing setup for hosting packages

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Cover ResponsesChannel custom path routing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align hosting tests with package layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix hosting workflow fixture imports in aggregate tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply useful Responses channel hardening

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix hosting package typing checks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix hosting pyright under Python 3.11

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Avoid static diskcache dependency in hosting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix aggregate typing and Docker test resilience

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Simplify local Responses workflow sample

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify generic hosting is not Foundry hosting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revert "Clarify generic hosting is not Foundry hosting"

This reverts commit 73b584d919053bed43a258d75dc2b76406e9c181.

* Clarify isolation key source flexibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify isolation header reuse boundary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Support multimodal Responses channel outputs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Preserve multimodal streaming Responses output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Stream Responses output items from updates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Improve Responses streaming output handling

* Tighten Responses channel default option handling

- Restore full option parsing in parse_responses_request: known fields
  are remapped (max_output_tokens→max_tokens, parallel_tool_calls→
  allow_multiple_tool_calls), transport/session keys excluded, None
  values dropped, everything else forwarded as-is so run_hook can
  inspect the full set.
- Add a default _strip_options_hook on ResponsesChannel that removes
  all parsed options before reaching the agent. Callers cannot inject
  generation params (temperature, instructions, tools, …) unless the
  host explicitly allows it.
- A custom run_hook replaces the default entirely and receives the
  full ChannelRequest.options plus the raw protocol_request.
- Update tests to cover remap, default-strip, and custom-hook paths.
- Clarify host debug-log docstring to match new option flow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-23 20:56:46 +00:00

123 lines
4.5 KiB
Markdown

# agent-framework-hosting
Multi-channel hosting for Microsoft Agent Framework agents.
`agent-framework-hosting` lets you serve a single agent or workflow target
through one or more **channels**. The host owns one Starlette ASGI app,
route/lifecycle composition, and per-`isolation_key` session resolution.
Each channel owns its protocol parsing and response rendering.
The base package contains only channel-neutral plumbing:
- `AgentFrameworkHost` — the Starlette host.
- `Channel` — the channel protocol.
- `ChannelRequest` / `ChannelSession` / `ChannelIdentity` — the request
envelope and optional channel metadata.
- `ChannelContext` / `ChannelContribution` / `ChannelCommand` — channel-side
hooks for invoking the target and contributing routes, commands, and
lifecycle callbacks.
- `ChannelRunHook` / `ChannelResponseHook` / `ChannelStreamUpdateHook`
host-invoked customization seams.
`ChannelStreamUpdateHook` applies to streamed updates only. It is not a
substitute for final-response redaction.
Concrete channels live in their own packages so you only install what you use:
| Package | Transport |
|---|---|
| `agent-framework-hosting-responses` | OpenAI Responses API |
Additional channel packages can build on the same host contract without adding
their protocol dependencies to the base package.
## Install
```bash
pip install agent-framework-hosting agent-framework-hosting-responses
# or with Hypercorn pre-installed for the demo `host.serve(...)` helper
pip install "agent-framework-hosting[serve]" agent-framework-hosting-responses
# add the [disk] extra to persist reset-session aliases
pip install "agent-framework-hosting[disk]"
```
## Quickstart
```python
from agent_framework.openai import OpenAIChatClient
from agent_framework_hosting import AgentFrameworkHost, Channel
agent = OpenAIChatClient().as_agent(name="Assistant")
# Add channels from sibling packages, e.g. `agent-framework-hosting-responses`
# exposes a `ResponsesChannel` that serves the OpenAI Responses API.
channels: list[Channel] = []
host = AgentFrameworkHost(target=agent, channels=channels)
host.serve(port=8000)
```
## Session state and workflow checkpoints
By default the host keeps live `AgentSession` objects and reset-session aliases
in memory. Channels opt into continuity by setting
`ChannelRequest.session = ChannelSession(isolation_key=...)`; requests with the
same isolation key reuse the same host-created session.
The host treats `isolation_key` as an opaque partition key. Each channel or
hosting environment decides where that key comes from:
- protocol headers supplied by a trusted platform,
- request body fields such as a previous response or conversation ID,
- route/path parameters,
- channel-native metadata such as chat/user IDs, or
- environment-provided context in an ephemeral host.
The host should be able to carry any of those sources as long as the channel or
platform has already authenticated and authorized the caller before passing the
key to `ChannelSession`.
The built-in request-context helper recognizes the `x-agent-user-isolation-key`
and `x-agent-chat-isolation-key` header names because some hosting
environments, including Foundry Hosted Agents, already use them. Reusing those
header names does **not** mean `agent-framework-hosting` is the supported way to
run on Foundry Hosted Agents; use `agent-framework-foundry-hosting` for that
hosting surface.
For long-running deployments that need `reset_session(...)` aliases to survive
restart, pass `state_dir`:
```python
host = AgentFrameworkHost(
target=agent,
channels=channels,
state_dir="./.host-state",
)
```
This creates `./.host-state/sessions/` and stores only lightweight alias
bookkeeping. Live `AgentSession` objects are still rehydrated lazily by the
configured history provider on the next turn.
For workflow targets, `checkpoint_location=...` is the clearest way to enable
checkpoint persistence. As a convenience, `state_dir="./.host-state"` also
derives `./.host-state/checkpoints/` for workflow targets. Use the mapping form
when you want only one component:
```python
from agent_framework_hosting import HostStatePaths
host = AgentFrameworkHost(
target=workflow,
channels=channels,
state_dir=HostStatePaths(
sessions="/var/lib/myapp/sessions",
checkpoints="/var/lib/myapp/checkpoints",
),
)
```
Cross-channel identity linking, multicast delivery, background runs,
continuation tokens, and durable delivery runners are follow-up enhancements,
not part of this v1 host contract.