ory-agent-framework 0.11.1__py3-none-any.whl
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.
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Ory Agent Security for the Microsoft Agent Framework.
|
|
2
|
+
|
|
3
|
+
from ory_agent_framework import ory_function_middleware
|
|
4
|
+
|
|
5
|
+
agent = chat_client.create_agent(
|
|
6
|
+
instructions="…",
|
|
7
|
+
tools=[search, send_email],
|
|
8
|
+
middleware=[ory_function_middleware()],
|
|
9
|
+
)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from .middleware import guarded_process, ory_function_middleware
|
|
15
|
+
|
|
16
|
+
__version__ = "0.11.1"
|
|
17
|
+
|
|
18
|
+
__all__ = ["ory_function_middleware", "guarded_process", "__version__"]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Ory Agent Security for the Microsoft Agent Framework.
|
|
2
|
+
|
|
3
|
+
The Agent Framework's per-tool interceptor is **function middleware** — ``process(context,
|
|
4
|
+
next)``. ``ory_function_middleware()`` authorizes each function/tool call against Ory
|
|
5
|
+
Permissions, traces it, and (on first call) runs the Ory session gates:
|
|
6
|
+
|
|
7
|
+
- allow / observe / fail-open / interactive → call ``next`` (the function runs) and record
|
|
8
|
+
``tool.complete``.
|
|
9
|
+
- deny (enforce) → set ``context.result`` to the denial and ``context.terminate = True``
|
|
10
|
+
*without* calling ``next``, so the function never runs.
|
|
11
|
+
|
|
12
|
+
Gate logic lives in ``ory_argus``. ``agent_framework`` is imported lazily, so importing this
|
|
13
|
+
module never requires it.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from ory_argus import GateResult, OryAgentClient, complete, gate, session_start
|
|
21
|
+
|
|
22
|
+
HARNESS = "agent-framework"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _extract(context: Any) -> tuple[str, Any]:
|
|
26
|
+
fn = getattr(context, "function", None)
|
|
27
|
+
name = (
|
|
28
|
+
getattr(fn, "name", None)
|
|
29
|
+
or getattr(context, "function_name", None)
|
|
30
|
+
or getattr(context, "name", None)
|
|
31
|
+
or "unknown"
|
|
32
|
+
)
|
|
33
|
+
args = getattr(context, "arguments", None) or getattr(context, "args", None)
|
|
34
|
+
return name, args
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def guarded_process(
|
|
38
|
+
client: OryAgentClient,
|
|
39
|
+
context: Any,
|
|
40
|
+
call_next: Any,
|
|
41
|
+
*,
|
|
42
|
+
can_block: bool = True,
|
|
43
|
+
project_url: str | None = None,
|
|
44
|
+
_session_state: dict | None = None,
|
|
45
|
+
) -> Any:
|
|
46
|
+
"""SDK-free guarded middleware body — testable with a fake context + next."""
|
|
47
|
+
state = _session_state if _session_state is not None else {}
|
|
48
|
+
if not state.get("started"):
|
|
49
|
+
state["started"] = True
|
|
50
|
+
try:
|
|
51
|
+
session_start(client, harness=HARNESS, project_url=project_url)
|
|
52
|
+
except Exception as err: # noqa: BLE001
|
|
53
|
+
client.logger.warn("session_start.failed", {"message": str(err)})
|
|
54
|
+
|
|
55
|
+
name, args = _extract(context)
|
|
56
|
+
result: GateResult = gate(client, harness=HARNESS, tool_name=name, tool_args=args, can_block=can_block)
|
|
57
|
+
if result.blocked:
|
|
58
|
+
# Short-circuit: set the result and terminate without calling next.
|
|
59
|
+
context.result = result.denial_message or "Ory: permission denied"
|
|
60
|
+
try:
|
|
61
|
+
context.terminate = True
|
|
62
|
+
except Exception: # noqa: BLE001 — some contexts may not expose terminate
|
|
63
|
+
pass
|
|
64
|
+
return None
|
|
65
|
+
out = await call_next(context)
|
|
66
|
+
complete(client, tool_name=name)
|
|
67
|
+
return out
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def ory_function_middleware(
|
|
71
|
+
*, client: OryAgentClient | None = None, can_block: bool = True, project_url: str | None = None
|
|
72
|
+
):
|
|
73
|
+
"""Return a function-middleware callable ``async (context, next)`` gated through Ory."""
|
|
74
|
+
c = client or OryAgentClient.from_env(HARNESS)
|
|
75
|
+
state: dict = {}
|
|
76
|
+
|
|
77
|
+
async def _middleware(context: Any, call_next: Any) -> Any:
|
|
78
|
+
return await guarded_process(
|
|
79
|
+
c, context, call_next, can_block=can_block, project_url=project_url, _session_state=state
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return _middleware
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
__all__ = ["HARNESS", "guarded_process", "ory_function_middleware"]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ory-agent-framework
|
|
3
|
+
Version: 0.11.1
|
|
4
|
+
Summary: Ory Agent Security for the Microsoft Agent Framework — per-tool authorization, tracing, and identity propagation via function middleware. Built on ory-argus.
|
|
5
|
+
Author: Ory
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Keywords: agent,agent-framework,ai,authorization,autogen,microsoft,ory
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: agent-framework>=0.0.0a1
|
|
10
|
+
Requires-Dist: ory-argus<1,>=0.8
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# ory-agent-framework
|
|
17
|
+
|
|
18
|
+
Ory Agent Security for the [Microsoft Agent Framework](https://learn.microsoft.com/agent-framework/)
|
|
19
|
+
(the successor to AutoGen + Semantic Kernel).
|
|
20
|
+
|
|
21
|
+
Gates every function/tool call through Ory Permissions via **function middleware**, traces
|
|
22
|
+
invocations, and propagates the user → agent identity — built on
|
|
23
|
+
[`ory-argus`](https://pypi.org/project/ory-argus/).
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install ory-agent-framework
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from ory_agent_framework import ory_function_middleware
|
|
31
|
+
|
|
32
|
+
agent = chat_client.create_agent(
|
|
33
|
+
instructions="…",
|
|
34
|
+
tools=[search, send_email],
|
|
35
|
+
middleware=[ory_function_middleware()],
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
In **enforce** mode (`ORY_PERMISSION_MODE=enforce`) a denied call sets the result to the
|
|
40
|
+
denial and terminates without invoking the function. In **observe** mode (default) the
|
|
41
|
+
function runs and a `permission.observe_deny` span is recorded.
|
|
42
|
+
|
|
43
|
+
Credentials come from the shared `~/.config/ory-agent-plugins/config.json`.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
ory_agent_framework/__init__.py,sha256=5nxXV5hmdAXCipVki2BJlBlBKUvFkc_RAdWRMsdB6ZY,478
|
|
2
|
+
ory_agent_framework/middleware.py,sha256=i421Mrp5OfH-MvZPpcwdwen1vNNCjAOk1hJcaRIUVWA,3069
|
|
3
|
+
ory_agent_framework-0.11.1.dist-info/METADATA,sha256=7guKUU2E1kCGTJcp2MMnzpEl5iTHjngLmrFElRHXmUk,1541
|
|
4
|
+
ory_agent_framework-0.11.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
5
|
+
ory_agent_framework-0.11.1.dist-info/RECORD,,
|