agent-framework-hosting 1.0.0a260625__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_framework_hosting-1.0.0a260625/LICENSE +21 -0
- agent_framework_hosting-1.0.0a260625/PKG-INFO +152 -0
- agent_framework_hosting-1.0.0a260625/README.md +122 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/__init__.py +66 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/_host.py +1425 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/_isolation.py +82 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/_persistence.py +128 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/_state_store.py +146 -0
- agent_framework_hosting-1.0.0a260625/agent_framework_hosting/_types.py +212 -0
- agent_framework_hosting-1.0.0a260625/pyproject.toml +92 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-framework-hosting
|
|
3
|
+
Version: 1.0.0a260625
|
|
4
|
+
Summary: Multi-channel hosting for Microsoft Agent Framework agents.
|
|
5
|
+
Author-email: Microsoft <af-support@microsoft.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: agent-framework-core>=1.10.0,<2
|
|
20
|
+
Requires-Dist: starlette>=0.37
|
|
21
|
+
Requires-Dist: diskcache>=5.6 ; extra == "disk"
|
|
22
|
+
Requires-Dist: hypercorn>=0.17 ; extra == "serve"
|
|
23
|
+
Project-URL: homepage, https://aka.ms/agent-framework
|
|
24
|
+
Project-URL: issues, https://github.com/microsoft/agent-framework/issues
|
|
25
|
+
Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
|
|
26
|
+
Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
|
|
27
|
+
Provides-Extra: disk
|
|
28
|
+
Provides-Extra: serve
|
|
29
|
+
|
|
30
|
+
# agent-framework-hosting
|
|
31
|
+
|
|
32
|
+
Multi-channel hosting for Microsoft Agent Framework agents.
|
|
33
|
+
|
|
34
|
+
`agent-framework-hosting` lets you serve a single agent or workflow target
|
|
35
|
+
through one or more **channels**. The host owns one Starlette ASGI app,
|
|
36
|
+
route/lifecycle composition, and per-`isolation_key` session resolution.
|
|
37
|
+
Each channel owns its protocol parsing and response rendering.
|
|
38
|
+
|
|
39
|
+
The base package contains only channel-neutral plumbing:
|
|
40
|
+
|
|
41
|
+
- `AgentFrameworkHost` — the Starlette host.
|
|
42
|
+
- `Channel` — the channel protocol.
|
|
43
|
+
- `ChannelRequest` / `ChannelSession` / `ChannelIdentity` — the request
|
|
44
|
+
envelope and optional channel metadata.
|
|
45
|
+
- `ChannelContext` / `ChannelContribution` / `ChannelCommand` — channel-side
|
|
46
|
+
hooks for invoking the target and contributing routes, commands, and
|
|
47
|
+
lifecycle callbacks.
|
|
48
|
+
- `ChannelRunHook` / `ChannelResponseHook` / `ChannelStreamUpdateHook` —
|
|
49
|
+
host-invoked customization seams.
|
|
50
|
+
|
|
51
|
+
`ChannelStreamUpdateHook` applies to streamed updates only. It is not a
|
|
52
|
+
substitute for final-response redaction.
|
|
53
|
+
|
|
54
|
+
Concrete channels live in their own packages so you only install what you use:
|
|
55
|
+
|
|
56
|
+
| Package | Transport |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `agent-framework-hosting-responses` | OpenAI Responses API |
|
|
59
|
+
|
|
60
|
+
Additional channel packages can build on the same host contract without adding
|
|
61
|
+
their protocol dependencies to the base package.
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install agent-framework-hosting agent-framework-hosting-responses
|
|
67
|
+
# or with Hypercorn pre-installed for the demo `host.serve(...)` helper
|
|
68
|
+
pip install "agent-framework-hosting[serve]" agent-framework-hosting-responses
|
|
69
|
+
# add the [disk] extra to persist reset-session aliases
|
|
70
|
+
pip install "agent-framework-hosting[disk]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Quickstart
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from agent_framework.openai import OpenAIChatClient
|
|
77
|
+
from agent_framework_hosting import AgentFrameworkHost, Channel
|
|
78
|
+
|
|
79
|
+
agent = OpenAIChatClient().as_agent(name="Assistant")
|
|
80
|
+
|
|
81
|
+
# Add channels from sibling packages, e.g. `agent-framework-hosting-responses`
|
|
82
|
+
# exposes a `ResponsesChannel` that serves the OpenAI Responses API.
|
|
83
|
+
channels: list[Channel] = []
|
|
84
|
+
|
|
85
|
+
host = AgentFrameworkHost(target=agent, channels=channels)
|
|
86
|
+
host.serve(port=8000)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Session state and workflow checkpoints
|
|
90
|
+
|
|
91
|
+
By default the host keeps live `AgentSession` objects and reset-session aliases
|
|
92
|
+
in memory. Channels opt into continuity by setting
|
|
93
|
+
`ChannelRequest.session = ChannelSession(isolation_key=...)`; requests with the
|
|
94
|
+
same isolation key reuse the same host-created session.
|
|
95
|
+
|
|
96
|
+
The host treats `isolation_key` as an opaque partition key. Each channel or
|
|
97
|
+
hosting environment decides where that key comes from:
|
|
98
|
+
|
|
99
|
+
- protocol headers supplied by a trusted platform,
|
|
100
|
+
- request body fields such as a previous response or conversation ID,
|
|
101
|
+
- route/path parameters,
|
|
102
|
+
- channel-native metadata such as chat/user IDs, or
|
|
103
|
+
- environment-provided context in an ephemeral host.
|
|
104
|
+
|
|
105
|
+
The host should be able to carry any of those sources as long as the channel or
|
|
106
|
+
platform has already authenticated and authorized the caller before passing the
|
|
107
|
+
key to `ChannelSession`.
|
|
108
|
+
|
|
109
|
+
The built-in request-context helper recognizes the `x-agent-user-isolation-key`
|
|
110
|
+
and `x-agent-chat-isolation-key` header names because some hosting
|
|
111
|
+
environments, including Foundry Hosted Agents, already use them. Reusing those
|
|
112
|
+
header names does **not** mean `agent-framework-hosting` is the supported way to
|
|
113
|
+
run on Foundry Hosted Agents; use `agent-framework-foundry-hosting` for that
|
|
114
|
+
hosting surface.
|
|
115
|
+
|
|
116
|
+
For long-running deployments that need `reset_session(...)` aliases to survive
|
|
117
|
+
restart, pass `state_dir`:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
host = AgentFrameworkHost(
|
|
121
|
+
target=agent,
|
|
122
|
+
channels=channels,
|
|
123
|
+
state_dir="./.host-state",
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This creates `./.host-state/sessions/` and stores only lightweight alias
|
|
128
|
+
bookkeeping. Live `AgentSession` objects are still rehydrated lazily by the
|
|
129
|
+
configured history provider on the next turn.
|
|
130
|
+
|
|
131
|
+
For workflow targets, `checkpoint_location=...` is the clearest way to enable
|
|
132
|
+
checkpoint persistence. As a convenience, `state_dir="./.host-state"` also
|
|
133
|
+
derives `./.host-state/checkpoints/` for workflow targets. Use the mapping form
|
|
134
|
+
when you want only one component:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from agent_framework_hosting import HostStatePaths
|
|
138
|
+
|
|
139
|
+
host = AgentFrameworkHost(
|
|
140
|
+
target=workflow,
|
|
141
|
+
channels=channels,
|
|
142
|
+
state_dir=HostStatePaths(
|
|
143
|
+
sessions="/var/lib/myapp/sessions",
|
|
144
|
+
checkpoints="/var/lib/myapp/checkpoints",
|
|
145
|
+
),
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Cross-channel identity linking, multicast delivery, background runs,
|
|
150
|
+
continuation tokens, and durable delivery runners are follow-up enhancements,
|
|
151
|
+
not part of this v1 host contract.
|
|
152
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# agent-framework-hosting
|
|
2
|
+
|
|
3
|
+
Multi-channel hosting for Microsoft Agent Framework agents.
|
|
4
|
+
|
|
5
|
+
`agent-framework-hosting` lets you serve a single agent or workflow target
|
|
6
|
+
through one or more **channels**. The host owns one Starlette ASGI app,
|
|
7
|
+
route/lifecycle composition, and per-`isolation_key` session resolution.
|
|
8
|
+
Each channel owns its protocol parsing and response rendering.
|
|
9
|
+
|
|
10
|
+
The base package contains only channel-neutral plumbing:
|
|
11
|
+
|
|
12
|
+
- `AgentFrameworkHost` — the Starlette host.
|
|
13
|
+
- `Channel` — the channel protocol.
|
|
14
|
+
- `ChannelRequest` / `ChannelSession` / `ChannelIdentity` — the request
|
|
15
|
+
envelope and optional channel metadata.
|
|
16
|
+
- `ChannelContext` / `ChannelContribution` / `ChannelCommand` — channel-side
|
|
17
|
+
hooks for invoking the target and contributing routes, commands, and
|
|
18
|
+
lifecycle callbacks.
|
|
19
|
+
- `ChannelRunHook` / `ChannelResponseHook` / `ChannelStreamUpdateHook` —
|
|
20
|
+
host-invoked customization seams.
|
|
21
|
+
|
|
22
|
+
`ChannelStreamUpdateHook` applies to streamed updates only. It is not a
|
|
23
|
+
substitute for final-response redaction.
|
|
24
|
+
|
|
25
|
+
Concrete channels live in their own packages so you only install what you use:
|
|
26
|
+
|
|
27
|
+
| Package | Transport |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `agent-framework-hosting-responses` | OpenAI Responses API |
|
|
30
|
+
|
|
31
|
+
Additional channel packages can build on the same host contract without adding
|
|
32
|
+
their protocol dependencies to the base package.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install agent-framework-hosting agent-framework-hosting-responses
|
|
38
|
+
# or with Hypercorn pre-installed for the demo `host.serve(...)` helper
|
|
39
|
+
pip install "agent-framework-hosting[serve]" agent-framework-hosting-responses
|
|
40
|
+
# add the [disk] extra to persist reset-session aliases
|
|
41
|
+
pip install "agent-framework-hosting[disk]"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from agent_framework.openai import OpenAIChatClient
|
|
48
|
+
from agent_framework_hosting import AgentFrameworkHost, Channel
|
|
49
|
+
|
|
50
|
+
agent = OpenAIChatClient().as_agent(name="Assistant")
|
|
51
|
+
|
|
52
|
+
# Add channels from sibling packages, e.g. `agent-framework-hosting-responses`
|
|
53
|
+
# exposes a `ResponsesChannel` that serves the OpenAI Responses API.
|
|
54
|
+
channels: list[Channel] = []
|
|
55
|
+
|
|
56
|
+
host = AgentFrameworkHost(target=agent, channels=channels)
|
|
57
|
+
host.serve(port=8000)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Session state and workflow checkpoints
|
|
61
|
+
|
|
62
|
+
By default the host keeps live `AgentSession` objects and reset-session aliases
|
|
63
|
+
in memory. Channels opt into continuity by setting
|
|
64
|
+
`ChannelRequest.session = ChannelSession(isolation_key=...)`; requests with the
|
|
65
|
+
same isolation key reuse the same host-created session.
|
|
66
|
+
|
|
67
|
+
The host treats `isolation_key` as an opaque partition key. Each channel or
|
|
68
|
+
hosting environment decides where that key comes from:
|
|
69
|
+
|
|
70
|
+
- protocol headers supplied by a trusted platform,
|
|
71
|
+
- request body fields such as a previous response or conversation ID,
|
|
72
|
+
- route/path parameters,
|
|
73
|
+
- channel-native metadata such as chat/user IDs, or
|
|
74
|
+
- environment-provided context in an ephemeral host.
|
|
75
|
+
|
|
76
|
+
The host should be able to carry any of those sources as long as the channel or
|
|
77
|
+
platform has already authenticated and authorized the caller before passing the
|
|
78
|
+
key to `ChannelSession`.
|
|
79
|
+
|
|
80
|
+
The built-in request-context helper recognizes the `x-agent-user-isolation-key`
|
|
81
|
+
and `x-agent-chat-isolation-key` header names because some hosting
|
|
82
|
+
environments, including Foundry Hosted Agents, already use them. Reusing those
|
|
83
|
+
header names does **not** mean `agent-framework-hosting` is the supported way to
|
|
84
|
+
run on Foundry Hosted Agents; use `agent-framework-foundry-hosting` for that
|
|
85
|
+
hosting surface.
|
|
86
|
+
|
|
87
|
+
For long-running deployments that need `reset_session(...)` aliases to survive
|
|
88
|
+
restart, pass `state_dir`:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
host = AgentFrameworkHost(
|
|
92
|
+
target=agent,
|
|
93
|
+
channels=channels,
|
|
94
|
+
state_dir="./.host-state",
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This creates `./.host-state/sessions/` and stores only lightweight alias
|
|
99
|
+
bookkeeping. Live `AgentSession` objects are still rehydrated lazily by the
|
|
100
|
+
configured history provider on the next turn.
|
|
101
|
+
|
|
102
|
+
For workflow targets, `checkpoint_location=...` is the clearest way to enable
|
|
103
|
+
checkpoint persistence. As a convenience, `state_dir="./.host-state"` also
|
|
104
|
+
derives `./.host-state/checkpoints/` for workflow targets. Use the mapping form
|
|
105
|
+
when you want only one component:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from agent_framework_hosting import HostStatePaths
|
|
109
|
+
|
|
110
|
+
host = AgentFrameworkHost(
|
|
111
|
+
target=workflow,
|
|
112
|
+
channels=channels,
|
|
113
|
+
state_dir=HostStatePaths(
|
|
114
|
+
sessions="/var/lib/myapp/sessions",
|
|
115
|
+
checkpoints="/var/lib/myapp/checkpoints",
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Cross-channel identity linking, multicast delivery, background runs,
|
|
121
|
+
continuation tokens, and durable delivery runners are follow-up enhancements,
|
|
122
|
+
not part of this v1 host contract.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Multi-channel hosting for Microsoft Agent Framework agents.
|
|
4
|
+
|
|
5
|
+
Serve a single agent target through one or more **channels** — pluggable
|
|
6
|
+
adapters that expose the target over different transports. The base
|
|
7
|
+
package contains only the channel-neutral plumbing; concrete channels
|
|
8
|
+
ship in their own packages, such as ``agent-framework-hosting-responses``,
|
|
9
|
+
so users install only what they need.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import importlib.metadata
|
|
13
|
+
|
|
14
|
+
from ._host import AgentFrameworkHost, ChannelContext, logger
|
|
15
|
+
from ._isolation import (
|
|
16
|
+
ISOLATION_HEADER_CHAT,
|
|
17
|
+
ISOLATION_HEADER_USER,
|
|
18
|
+
IsolationKeys,
|
|
19
|
+
get_current_isolation_keys,
|
|
20
|
+
reset_current_isolation_keys,
|
|
21
|
+
set_current_isolation_keys,
|
|
22
|
+
)
|
|
23
|
+
from ._types import (
|
|
24
|
+
Channel,
|
|
25
|
+
ChannelCommand,
|
|
26
|
+
ChannelCommandContext,
|
|
27
|
+
ChannelContribution,
|
|
28
|
+
ChannelIdentity,
|
|
29
|
+
ChannelRequest,
|
|
30
|
+
ChannelResponseHook,
|
|
31
|
+
ChannelRunHook,
|
|
32
|
+
ChannelSession,
|
|
33
|
+
ChannelStreamUpdateHook,
|
|
34
|
+
HostedRunResult,
|
|
35
|
+
HostStatePaths,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
__version__ = importlib.metadata.version(__name__)
|
|
40
|
+
except importlib.metadata.PackageNotFoundError:
|
|
41
|
+
__version__ = "0.0.0"
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
"ISOLATION_HEADER_CHAT",
|
|
45
|
+
"ISOLATION_HEADER_USER",
|
|
46
|
+
"AgentFrameworkHost",
|
|
47
|
+
"Channel",
|
|
48
|
+
"ChannelCommand",
|
|
49
|
+
"ChannelCommandContext",
|
|
50
|
+
"ChannelContext",
|
|
51
|
+
"ChannelContribution",
|
|
52
|
+
"ChannelIdentity",
|
|
53
|
+
"ChannelRequest",
|
|
54
|
+
"ChannelResponseHook",
|
|
55
|
+
"ChannelRunHook",
|
|
56
|
+
"ChannelSession",
|
|
57
|
+
"ChannelStreamUpdateHook",
|
|
58
|
+
"HostStatePaths",
|
|
59
|
+
"HostedRunResult",
|
|
60
|
+
"IsolationKeys",
|
|
61
|
+
"__version__",
|
|
62
|
+
"get_current_isolation_keys",
|
|
63
|
+
"logger",
|
|
64
|
+
"reset_current_isolation_keys",
|
|
65
|
+
"set_current_isolation_keys",
|
|
66
|
+
]
|