azurefunctions-agents-extensions-agent-framework 1.0.0b1__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.
Files changed (23) hide show
  1. azurefunctions_agents_extensions_agent_framework-1.0.0b1/LICENSE +21 -0
  2. azurefunctions_agents_extensions_agent_framework-1.0.0b1/MANIFEST.in +3 -0
  3. azurefunctions_agents_extensions_agent_framework-1.0.0b1/PKG-INFO +195 -0
  4. azurefunctions_agents_extensions_agent_framework-1.0.0b1/README.md +157 -0
  5. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/__init__.py +1 -0
  6. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/__init__.py +1 -0
  7. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/extensions/__init__.py +1 -0
  8. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/extensions/agent_framework/__init__.py +13 -0
  9. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/extensions/agent_framework/apps.py +103 -0
  10. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/extensions/agent_framework/provider.py +327 -0
  11. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions/agents/extensions/agent_framework/py.typed +1 -0
  12. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/PKG-INFO +195 -0
  13. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/SOURCES.txt +21 -0
  14. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/dependency_links.txt +1 -0
  15. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/entry_points.txt +2 -0
  16. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/requires.txt +20 -0
  17. azurefunctions_agents_extensions_agent_framework-1.0.0b1/azurefunctions_agents_extensions_agent_framework.egg-info/top_level.txt +1 -0
  18. azurefunctions_agents_extensions_agent_framework-1.0.0b1/pyproject.toml +69 -0
  19. azurefunctions_agents_extensions_agent_framework-1.0.0b1/setup.cfg +4 -0
  20. azurefunctions_agents_extensions_agent_framework-1.0.0b1/tests/test_apps.py +117 -0
  21. azurefunctions_agents_extensions_agent_framework-1.0.0b1/tests/test_imports.py +38 -0
  22. azurefunctions_agents_extensions_agent_framework-1.0.0b1/tests/test_provider.py +472 -0
  23. azurefunctions_agents_extensions_agent_framework-1.0.0b1/tests/test_samples.py +170 -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,3 @@
1
+ recursive-include azurefunctions *.py *.pyi
2
+ recursive-include tests *.py
3
+ include LICENSE README.md
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: azurefunctions-agents-extensions-agent-framework
3
+ Version: 1.0.0b1
4
+ Summary: Microsoft Agent Framework integration for Azure Functions.
5
+ Author-email: "Azure Functions team at Microsoft Corp." <azurefunctions@microsoft.com>
6
+ License: MIT License
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: POSIX
14
+ Classifier: Operating System :: MacOS :: MacOS X
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Development Status :: 3 - Alpha
17
+ Requires-Python: >=3.13
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: agent-framework-core<2,>=1.13.0
21
+ Requires-Dist: azurefunctions-agents-extensions-base>=1.0.0b1
22
+ Provides-Extra: mcp
23
+ Requires-Dist: azure-identity<2,>=1.25.3; extra == "mcp"
24
+ Requires-Dist: httpx<1,>=0.27; extra == "mcp"
25
+ Requires-Dist: mcp<2,>=1.28.1; extra == "mcp"
26
+ Provides-Extra: durable
27
+ Requires-Dist: azurefunctions-agents-extensions-base[durable]>=1.0.0b1; extra == "durable"
28
+ Provides-Extra: dev
29
+ Requires-Dist: azure-functions-durable>=2.0.0b2; extra == "dev"
30
+ Requires-Dist: coverage; extra == "dev"
31
+ Requires-Dist: flake8; extra == "dev"
32
+ Requires-Dist: mypy; extra == "dev"
33
+ Requires-Dist: pre-commit; extra == "dev"
34
+ Requires-Dist: pytest; extra == "dev"
35
+ Requires-Dist: pytest-cov; extra == "dev"
36
+ Requires-Dist: pytest-instafail; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # Azure Functions Microsoft Agent Framework Extension
40
+
41
+ Inject Microsoft Agent Framework Agents built from raw `.agent.md` instructions
42
+ into Python Azure Functions.
43
+
44
+ ## Install
45
+
46
+ ```text
47
+ pip install azurefunctions-agents-extensions-agent-framework
48
+ ```
49
+
50
+ Install Durable Functions support with the durable extra:
51
+
52
+ ```text
53
+ pip install "azurefunctions-agents-extensions-agent-framework[durable]"
54
+ ```
55
+
56
+
57
+ Install remote MCP transport and Entra support with the MCP extra:
58
+
59
+ ```text
60
+ pip install "azurefunctions-agents-extensions-agent-framework[mcp]"
61
+ ```
62
+
63
+ ## Use an Agent app
64
+
65
+ Create a zero-argument factory that returns a fresh MAF chat client. A new
66
+ client and Agent context are created and closed for every Function invocation.
67
+
68
+ ```python
69
+ import azure.functions as func
70
+ from agent_framework import Agent
71
+ from azurefunctions.agents.extensions.agent_framework import AgentFunctionApp
72
+
73
+
74
+ def create_chat_client():
75
+ from agent_framework.openai import OpenAIChatClient
76
+
77
+ return OpenAIChatClient()
78
+
79
+
80
+ app = AgentFunctionApp(client_factory=create_chat_client)
81
+
82
+
83
+ @app.route(route="orders", methods=["POST"])
84
+ @app.markdown_agent(arg_name="agent", agent_name="orders")
85
+ async def process_order(req: func.HttpRequest, agent: Agent):
86
+ response = await agent.run(req.get_body().decode())
87
+ return response.text
88
+ ```
89
+
90
+ `AgentFunctionApp` is owned by this extension and subclasses
91
+ `azure.functions.FunctionApp`. The Azure Functions SDK does not need Agent APIs
92
+ or modifications. One app uses the Microsoft Agent Framework provider selected
93
+ by this package.
94
+
95
+ Place the complete instructions at `orders.agent.md` or
96
+ `agents/orders.agent.md`. The file is raw UTF-8 text; no front matter or runtime
97
+ configuration is interpreted.
98
+
99
+ ## Skills and MCP servers
100
+
101
+ Skills and MCP servers are discovered automatically from the app root and are
102
+ available to each Agent binding by default:
103
+
104
+ ```text
105
+ skills/inventory/SKILL.md
106
+ mcp.json
107
+ ```
108
+
109
+ `SKILL.md` uses Agent Skills frontmatter:
110
+
111
+ ```markdown
112
+ ---
113
+ name: inventory
114
+ description: Look up inventory policy and warehouse constraints.
115
+ ---
116
+
117
+ Use the references in this skill when assessing stock.
118
+ ```
119
+
120
+ The base extension discovers Skill directory paths without reading their
121
+ contents. Microsoft Agent Framework parses and validates each `SKILL.md` when
122
+ it loads the file-based Skills provider.
123
+
124
+ V1 MCP discovery supports remote HTTP transports only:
125
+
126
+ ```json
127
+ {
128
+ "servers": {
129
+ "inventory": {
130
+ "type": "streamable-http",
131
+ "url": "$INVENTORY_MCP_URL",
132
+ "tools": ["lookup_stock", "reserve_stock"],
133
+ "headers": {"X-Tenant": "%TENANT_ID%"},
134
+ "auth": {
135
+ "scope": "$INVENTORY_MCP_SCOPE",
136
+ "client_id": "%AZURE_CLIENT_ID%"
137
+ }
138
+ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ `$VAR` and `%VAR%` references are resolved for each invocation, not during
144
+ discovery. Missing values fail before connecting. Servers configured with
145
+ headers or Entra authentication must use HTTPS; HTTP is accepted only for
146
+ loopback development. Exposed MCP tool names are prefixed with the server name
147
+ to prevent collisions between servers. Credentials, tokens, HTTP clients, MCP
148
+ tools, and Agents are fresh invocation-owned resources and are closed on
149
+ success, error, or cancellation. Do not place secrets directly in
150
+ source-controlled `mcp.json`; use environment references.
151
+
152
+ Every Agent in the Function App receives all valid Skills and MCP servers
153
+ discovered from the app root:
154
+
155
+ ```python
156
+ from azurefunctions.agents.extensions.agent_framework import AgentFunctionApp
157
+
158
+ app = AgentFunctionApp(client_factory=create_chat_client)
159
+
160
+
161
+ @app.markdown_agent(arg_name="agent", agent_name="orders")
162
+ async def process_order(agent: Agent):
163
+ ...
164
+ ```
165
+
166
+ V1 has no app-level or per-binding capability selectors. Skill scripts and MCP
167
+ tools can perform privileged operations, so placing a definition under the app
168
+ root grants every Agent in that app access to it. Use separate Function Apps
169
+ when capabilities require isolation. Python `tools=` remain explicit because
170
+ they are supplied directly to the Microsoft Agent Framework Agent.
171
+
172
+ The constructor and decorator expose only `client_factory` and explicit Python
173
+ `tools` in V1. The extension owns the Agent client, name, instructions, and
174
+ discovered Skills/MCP integration. Configure `app_root` only when constructing
175
+ `AgentFunctionApp`; decorators do not override it.
176
+
177
+ ## Durable Agents
178
+
179
+ Durable orchestration support is optional:
180
+
181
+ ```text
182
+ pip install "azurefunctions-agents-extensions-agent-framework[durable]"
183
+ ```
184
+
185
+ Use `AgentFunctionApp` and call `context.call_agent(agent_name, input_)` inside a
186
+ synchronous generator orchestrator. Agent execution is isolated in an activity
187
+ so replay performs no nondeterministic work. Importing the package remains safe
188
+ without Durable installed; using a Durable decorator requires the `[durable]`
189
+ extra.
190
+
191
+ All `call_agent()` invocations use the provider configured by `AgentFunctionApp`.
192
+ They also use the app-level `skills` and `mcp_servers` defaults. V1 does not
193
+ support selecting another provider or capability set from an orchestrator, and
194
+ the schema-v1 orchestration payload contains no capability paths, settings, or
195
+ secrets.
@@ -0,0 +1,157 @@
1
+ # Azure Functions Microsoft Agent Framework Extension
2
+
3
+ Inject Microsoft Agent Framework Agents built from raw `.agent.md` instructions
4
+ into Python Azure Functions.
5
+
6
+ ## Install
7
+
8
+ ```text
9
+ pip install azurefunctions-agents-extensions-agent-framework
10
+ ```
11
+
12
+ Install Durable Functions support with the durable extra:
13
+
14
+ ```text
15
+ pip install "azurefunctions-agents-extensions-agent-framework[durable]"
16
+ ```
17
+
18
+
19
+ Install remote MCP transport and Entra support with the MCP extra:
20
+
21
+ ```text
22
+ pip install "azurefunctions-agents-extensions-agent-framework[mcp]"
23
+ ```
24
+
25
+ ## Use an Agent app
26
+
27
+ Create a zero-argument factory that returns a fresh MAF chat client. A new
28
+ client and Agent context are created and closed for every Function invocation.
29
+
30
+ ```python
31
+ import azure.functions as func
32
+ from agent_framework import Agent
33
+ from azurefunctions.agents.extensions.agent_framework import AgentFunctionApp
34
+
35
+
36
+ def create_chat_client():
37
+ from agent_framework.openai import OpenAIChatClient
38
+
39
+ return OpenAIChatClient()
40
+
41
+
42
+ app = AgentFunctionApp(client_factory=create_chat_client)
43
+
44
+
45
+ @app.route(route="orders", methods=["POST"])
46
+ @app.markdown_agent(arg_name="agent", agent_name="orders")
47
+ async def process_order(req: func.HttpRequest, agent: Agent):
48
+ response = await agent.run(req.get_body().decode())
49
+ return response.text
50
+ ```
51
+
52
+ `AgentFunctionApp` is owned by this extension and subclasses
53
+ `azure.functions.FunctionApp`. The Azure Functions SDK does not need Agent APIs
54
+ or modifications. One app uses the Microsoft Agent Framework provider selected
55
+ by this package.
56
+
57
+ Place the complete instructions at `orders.agent.md` or
58
+ `agents/orders.agent.md`. The file is raw UTF-8 text; no front matter or runtime
59
+ configuration is interpreted.
60
+
61
+ ## Skills and MCP servers
62
+
63
+ Skills and MCP servers are discovered automatically from the app root and are
64
+ available to each Agent binding by default:
65
+
66
+ ```text
67
+ skills/inventory/SKILL.md
68
+ mcp.json
69
+ ```
70
+
71
+ `SKILL.md` uses Agent Skills frontmatter:
72
+
73
+ ```markdown
74
+ ---
75
+ name: inventory
76
+ description: Look up inventory policy and warehouse constraints.
77
+ ---
78
+
79
+ Use the references in this skill when assessing stock.
80
+ ```
81
+
82
+ The base extension discovers Skill directory paths without reading their
83
+ contents. Microsoft Agent Framework parses and validates each `SKILL.md` when
84
+ it loads the file-based Skills provider.
85
+
86
+ V1 MCP discovery supports remote HTTP transports only:
87
+
88
+ ```json
89
+ {
90
+ "servers": {
91
+ "inventory": {
92
+ "type": "streamable-http",
93
+ "url": "$INVENTORY_MCP_URL",
94
+ "tools": ["lookup_stock", "reserve_stock"],
95
+ "headers": {"X-Tenant": "%TENANT_ID%"},
96
+ "auth": {
97
+ "scope": "$INVENTORY_MCP_SCOPE",
98
+ "client_id": "%AZURE_CLIENT_ID%"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ `$VAR` and `%VAR%` references are resolved for each invocation, not during
106
+ discovery. Missing values fail before connecting. Servers configured with
107
+ headers or Entra authentication must use HTTPS; HTTP is accepted only for
108
+ loopback development. Exposed MCP tool names are prefixed with the server name
109
+ to prevent collisions between servers. Credentials, tokens, HTTP clients, MCP
110
+ tools, and Agents are fresh invocation-owned resources and are closed on
111
+ success, error, or cancellation. Do not place secrets directly in
112
+ source-controlled `mcp.json`; use environment references.
113
+
114
+ Every Agent in the Function App receives all valid Skills and MCP servers
115
+ discovered from the app root:
116
+
117
+ ```python
118
+ from azurefunctions.agents.extensions.agent_framework import AgentFunctionApp
119
+
120
+ app = AgentFunctionApp(client_factory=create_chat_client)
121
+
122
+
123
+ @app.markdown_agent(arg_name="agent", agent_name="orders")
124
+ async def process_order(agent: Agent):
125
+ ...
126
+ ```
127
+
128
+ V1 has no app-level or per-binding capability selectors. Skill scripts and MCP
129
+ tools can perform privileged operations, so placing a definition under the app
130
+ root grants every Agent in that app access to it. Use separate Function Apps
131
+ when capabilities require isolation. Python `tools=` remain explicit because
132
+ they are supplied directly to the Microsoft Agent Framework Agent.
133
+
134
+ The constructor and decorator expose only `client_factory` and explicit Python
135
+ `tools` in V1. The extension owns the Agent client, name, instructions, and
136
+ discovered Skills/MCP integration. Configure `app_root` only when constructing
137
+ `AgentFunctionApp`; decorators do not override it.
138
+
139
+ ## Durable Agents
140
+
141
+ Durable orchestration support is optional:
142
+
143
+ ```text
144
+ pip install "azurefunctions-agents-extensions-agent-framework[durable]"
145
+ ```
146
+
147
+ Use `AgentFunctionApp` and call `context.call_agent(agent_name, input_)` inside a
148
+ synchronous generator orchestrator. Agent execution is isolated in an activity
149
+ so replay performs no nondeterministic work. Importing the package remains safe
150
+ without Durable installed; using a Durable decorator requires the `[durable]`
151
+ extra.
152
+
153
+ All `call_agent()` invocations use the provider configured by `AgentFunctionApp`.
154
+ They also use the app-level `skills` and `mcp_servers` defaults. V1 does not
155
+ support selecting another provider or capability set from an orchestrator, and
156
+ the schema-v1 orchestration payload contains no capability paths, settings, or
157
+ secrets.
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1,13 @@
1
+ from azurefunctions.agents.extensions.base.durable import DurableAgentContext
2
+
3
+ from .apps import AgentFunctionApp
4
+ from .provider import AGENT_FRAMEWORK_PROVIDER_ID, ClientFactory
5
+
6
+ __all__ = [
7
+ "AGENT_FRAMEWORK_PROVIDER_ID",
8
+ "AgentFunctionApp",
9
+ "ClientFactory",
10
+ "DurableAgentContext",
11
+ ]
12
+
13
+ __version__ = '1.0.0b1'
@@ -0,0 +1,103 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from collections.abc import Callable, Sequence
5
+ from typing import Any, TypeVar
6
+
7
+ import azure.functions as func
8
+ from agent_framework import ToolTypes
9
+
10
+ from azurefunctions.agents.extensions.base import (
11
+ configure_app,
12
+ durable_orchestration_trigger,
13
+ )
14
+ from azurefunctions.agents.extensions.base import markdown_agent as base_markdown_agent
15
+
16
+ from .provider import AGENT_FRAMEWORK_PROVIDER_ID, ClientFactory
17
+
18
+ _F = TypeVar("_F", bound=Callable[..., Any])
19
+
20
+
21
+ def _provider_options(
22
+ *,
23
+ client_factory: ClientFactory | None = None,
24
+ tools: (
25
+ ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None
26
+ ) = None,
27
+ ) -> dict[str, object]:
28
+ options: dict[str, object] = {}
29
+ if client_factory is not None:
30
+ options["client_factory"] = client_factory
31
+ if tools is not None:
32
+ options["tools"] = tools
33
+ return options
34
+
35
+
36
+ class _AgentFrameworkAppMixin:
37
+ def markdown_agent(
38
+ self,
39
+ *,
40
+ arg_name: str,
41
+ agent_name: str,
42
+ client_factory: ClientFactory | None = None,
43
+ tools: (
44
+ ToolTypes
45
+ | Callable[..., Any]
46
+ | Sequence[ToolTypes | Callable[..., Any]]
47
+ | None
48
+ ) = None,
49
+ ) -> Callable[[_F], _F]:
50
+ return base_markdown_agent(
51
+ self,
52
+ provider=AGENT_FRAMEWORK_PROVIDER_ID,
53
+ arg_name=arg_name,
54
+ agent_name=agent_name,
55
+ **_provider_options(client_factory=client_factory, tools=tools),
56
+ )
57
+
58
+
59
+ class AgentFunctionApp(
60
+ _AgentFrameworkAppMixin,
61
+ func.FunctionApp,
62
+ ):
63
+ """Azure Functions app configured for Microsoft Agent Framework Agents."""
64
+
65
+ def __init__(
66
+ self,
67
+ *,
68
+ client_factory: ClientFactory,
69
+ app_root: str | os.PathLike[str] | None = None,
70
+ tools: (
71
+ ToolTypes
72
+ | Callable[..., Any]
73
+ | Sequence[ToolTypes | Callable[..., Any]]
74
+ | None
75
+ ) = None,
76
+ http_auth_level: func.AuthLevel | str = func.AuthLevel.FUNCTION,
77
+ ) -> None:
78
+ super().__init__(
79
+ http_auth_level=http_auth_level,
80
+ )
81
+ configure_app(
82
+ self,
83
+ provider=AGENT_FRAMEWORK_PROVIDER_ID,
84
+ app_root=app_root,
85
+ provider_options=_provider_options(
86
+ client_factory=client_factory,
87
+ tools=tools,
88
+ ),
89
+ )
90
+
91
+ def orchestration_trigger(
92
+ self,
93
+ context_name: str,
94
+ orchestration: str | None = None,
95
+ input_type: type | None = None,
96
+ ) -> Callable[..., Any]:
97
+ return durable_orchestration_trigger(
98
+ self,
99
+ sdk_decorator=super().orchestration_trigger,
100
+ context_name=context_name,
101
+ orchestration=orchestration,
102
+ input_type=input_type,
103
+ )