agenticdome-python-sdk 1.2.2__py3-none-any.whl → 1.2.3__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.
- {agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/METADATA +140 -21
- {agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/RECORD +6 -5
- agenticdome_sdk/autogen.py +709 -0
- {agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/WHEEL +0 -0
- {agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/licenses/LICENSE +0 -0
- {agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agenticdome-python-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: Official Python SDK for AgenticDome security guardrails, DLP, tool authorization, and multi-agent delegation enforcement.
|
|
5
5
|
Author: AgenticDome
|
|
6
6
|
License: Proprietary
|
|
@@ -27,36 +27,40 @@ License-File: LICENSE
|
|
|
27
27
|
Requires-Dist: requests>=2.31.0
|
|
28
28
|
Requires-Dist: urllib3>=2.0.0
|
|
29
29
|
Provides-Extra: crewai
|
|
30
|
-
Requires-Dist: crewai
|
|
30
|
+
Requires-Dist: crewai<=1.15.6,>=1.15.5; extra == "crewai"
|
|
31
31
|
Provides-Extra: redis
|
|
32
32
|
Requires-Dist: redis>=4.5.0; extra == "redis"
|
|
33
33
|
Provides-Extra: pop
|
|
34
34
|
Requires-Dist: cryptography>=42.0.0; extra == "pop"
|
|
35
35
|
Provides-Extra: pydanticai
|
|
36
|
-
Requires-Dist: pydantic-ai
|
|
36
|
+
Requires-Dist: pydantic-ai<=2.18.0,>=2.16.0; extra == "pydanticai"
|
|
37
37
|
Requires-Dist: anyio>=4.0.0; extra == "pydanticai"
|
|
38
38
|
Provides-Extra: pydantic
|
|
39
|
-
Requires-Dist: pydantic-ai
|
|
39
|
+
Requires-Dist: pydantic-ai<=2.18.0,>=2.16.0; extra == "pydantic"
|
|
40
40
|
Requires-Dist: anyio>=4.0.0; extra == "pydantic"
|
|
41
41
|
Provides-Extra: langgraph
|
|
42
42
|
Requires-Dist: langgraph==1.2.9; extra == "langgraph"
|
|
43
|
-
Requires-Dist: langchain-core
|
|
43
|
+
Requires-Dist: langchain-core<=1.5.1,>=1.5.0; extra == "langgraph"
|
|
44
44
|
Requires-Dist: langchain-openai==1.3.5; extra == "langgraph"
|
|
45
45
|
Requires-Dist: anyio>=4.0.0; extra == "langgraph"
|
|
46
46
|
Provides-Extra: microsoft
|
|
47
|
+
Provides-Extra: autogen
|
|
48
|
+
Requires-Dist: autogen-agentchat==0.7.5; extra == "autogen"
|
|
49
|
+
Provides-Extra: microsoft-autogen
|
|
50
|
+
Requires-Dist: autogen-agentchat==0.7.5; extra == "microsoft-autogen"
|
|
47
51
|
Provides-Extra: foundry
|
|
48
52
|
Requires-Dist: azure-ai-projects==2.3.0; extra == "foundry"
|
|
49
53
|
Requires-Dist: azure-identity==1.25.3; extra == "foundry"
|
|
50
54
|
Provides-Extra: agno
|
|
51
|
-
Requires-Dist: agno
|
|
55
|
+
Requires-Dist: agno<=2.8.3,>=2.8.0; extra == "agno"
|
|
52
56
|
Provides-Extra: openai-agents
|
|
53
57
|
Requires-Dist: openai-agents==0.18.3; extra == "openai-agents"
|
|
54
58
|
Provides-Extra: mcp
|
|
55
59
|
Requires-Dist: mcp<=1.28.1,>=1.26.0; extra == "mcp"
|
|
56
60
|
Provides-Extra: bedrock
|
|
57
|
-
Requires-Dist: boto3
|
|
61
|
+
Requires-Dist: boto3<=1.43.56,>=1.43.54; extra == "bedrock"
|
|
58
62
|
Provides-Extra: aws-bedrock
|
|
59
|
-
Requires-Dist: boto3
|
|
63
|
+
Requires-Dist: boto3<=1.43.56,>=1.43.54; extra == "aws-bedrock"
|
|
60
64
|
Provides-Extra: llamaindex
|
|
61
65
|
Requires-Dist: llama-index==0.14.23; extra == "llamaindex"
|
|
62
66
|
Provides-Extra: llama-index
|
|
@@ -66,29 +70,30 @@ Requires-Dist: google-adk==2.5.0; extra == "google-adk"
|
|
|
66
70
|
Provides-Extra: adk
|
|
67
71
|
Requires-Dist: google-adk==2.5.0; extra == "adk"
|
|
68
72
|
Provides-Extra: claude
|
|
69
|
-
Requires-Dist: claude-agent-sdk
|
|
73
|
+
Requires-Dist: claude-agent-sdk<=0.2.128,>=0.2.126; extra == "claude"
|
|
70
74
|
Provides-Extra: claude-agent-sdk
|
|
71
|
-
Requires-Dist: claude-agent-sdk
|
|
75
|
+
Requires-Dist: claude-agent-sdk<=0.2.128,>=0.2.126; extra == "claude-agent-sdk"
|
|
72
76
|
Provides-Extra: smolagents
|
|
73
77
|
Requires-Dist: smolagents==1.26.0; extra == "smolagents"
|
|
74
78
|
Provides-Extra: all
|
|
75
|
-
Requires-Dist: crewai
|
|
79
|
+
Requires-Dist: crewai<=1.15.6,>=1.15.5; extra == "all"
|
|
76
80
|
Requires-Dist: redis>=4.5.0; extra == "all"
|
|
77
81
|
Requires-Dist: cryptography>=42.0.0; extra == "all"
|
|
78
|
-
Requires-Dist: pydantic-ai
|
|
82
|
+
Requires-Dist: pydantic-ai<=2.18.0,>=2.16.0; extra == "all"
|
|
79
83
|
Requires-Dist: anyio>=4.0.0; extra == "all"
|
|
80
84
|
Requires-Dist: langgraph==1.2.9; extra == "all"
|
|
81
|
-
Requires-Dist: langchain-core
|
|
85
|
+
Requires-Dist: langchain-core<=1.5.1,>=1.5.0; extra == "all"
|
|
82
86
|
Requires-Dist: langchain-openai==1.3.5; extra == "all"
|
|
83
|
-
Requires-Dist:
|
|
87
|
+
Requires-Dist: autogen-agentchat==0.7.5; extra == "all"
|
|
88
|
+
Requires-Dist: agno<=2.8.3,>=2.8.0; extra == "all"
|
|
84
89
|
Requires-Dist: azure-ai-projects==2.3.0; extra == "all"
|
|
85
90
|
Requires-Dist: azure-identity==1.25.3; extra == "all"
|
|
86
91
|
Requires-Dist: openai-agents==0.18.3; extra == "all"
|
|
87
92
|
Requires-Dist: mcp<=1.28.1,>=1.26.0; extra == "all"
|
|
88
|
-
Requires-Dist: boto3
|
|
93
|
+
Requires-Dist: boto3<=1.43.56,>=1.43.54; extra == "all"
|
|
89
94
|
Requires-Dist: llama-index==0.14.23; extra == "all"
|
|
90
95
|
Requires-Dist: google-adk==2.5.0; extra == "all"
|
|
91
|
-
Requires-Dist: claude-agent-sdk
|
|
96
|
+
Requires-Dist: claude-agent-sdk<=0.2.128,>=0.2.126; extra == "all"
|
|
92
97
|
Requires-Dist: smolagents==1.26.0; extra == "all"
|
|
93
98
|
Provides-Extra: dev
|
|
94
99
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
@@ -109,7 +114,7 @@ Dynamic: license-file
|
|
|
109
114
|
|
|
110
115
|
`agenticdome-python-sdk` is the official Python SDK and middleware package for [AgenticDome](https://agenticdome.io). It enforces deterministic security controls at every boundary your agents cross — prompt ingress, tool execution, agent-to-agent handoffs, and output egress — backed by the AgenticDome central policy plane.
|
|
111
116
|
|
|
112
|
-
**One security pattern,
|
|
117
|
+
**One security pattern, fifteen runtimes:** CrewAI · PydanticAI · LangGraph/LangChain · Microsoft Agent Framework · Microsoft AutoGen · Microsoft AI Foundry · OpenAI Agents SDK · Claude Agent SDK · Hugging Face smolagents · Agno · Google ADK · LlamaIndex · AWS Bedrock · MCP hosts/gateways · custom Python.
|
|
113
118
|
|
|
114
119
|
```python
|
|
115
120
|
# The 30-second version: block a prompt-injected refund before it executes.
|
|
@@ -131,7 +136,7 @@ result = crew.kickoff() # hostile prompts, unsafe tools, and rogue
|
|
|
131
136
|
5. [Configuration](#configuration)
|
|
132
137
|
6. [Choosing Your Integration Point](#choosing-your-integration-point)
|
|
133
138
|
7. [Framework Integrations](#framework-integrations)
|
|
134
|
-
- [CrewAI](#crewai) · [PydanticAI](#pydanticai) · [LangGraph](#langgraph) · [Microsoft Agent Framework](#microsoft-agent-framework) · [Microsoft AI Foundry](#microsoft-ai-foundry) · [OpenAI Agents SDK](#openai-agents-sdk) · [Agno](#agno) · [Google ADK](#google-adk) · [LlamaIndex](#llamaindex) · [AWS Bedrock](#aws-bedrock) · [MCP Host / Gateway](#mcp-host--gateway)
|
|
139
|
+
- [CrewAI](#crewai) · [PydanticAI](#pydanticai) · [LangGraph](#langgraph) · [Microsoft Agent Framework](#microsoft-agent-framework) · [Microsoft AutoGen](#microsoft-autogen) · [Microsoft AI Foundry](#microsoft-ai-foundry) · [OpenAI Agents SDK](#openai-agents-sdk) · [Agno](#agno) · [Google ADK](#google-adk) · [LlamaIndex](#llamaindex) · [AWS Bedrock](#aws-bedrock) · [MCP Host / Gateway](#mcp-host--gateway)
|
|
135
140
|
8. [Core SDK Client (Custom Runtimes)](#core-sdk-client-custom-runtimes)
|
|
136
141
|
9. [Production Deployment](#production-deployment)
|
|
137
142
|
10. [Package Build and Verification](#package-build-and-verification)
|
|
@@ -276,6 +281,8 @@ result = crew.kickoff()
|
|
|
276
281
|
|
|
277
282
|
```bash
|
|
278
283
|
python examples/attack_demo.py --framework crewai --scenario refund_hijack
|
|
284
|
+
python examples/attack_demo.py --framework claude --scenario metadata_exfil
|
|
285
|
+
python examples/attack_demo.py --framework smolagents --scenario generated_code_exfil
|
|
279
286
|
```
|
|
280
287
|
|
|
281
288
|
---
|
|
@@ -294,6 +301,7 @@ pip install agenticdome-python-sdk
|
|
|
294
301
|
| PydanticAI | `pip install "agenticdome-python-sdk[pydanticai]"` |
|
|
295
302
|
| LangGraph / LangChain | `pip install "agenticdome-python-sdk[langgraph]"` |
|
|
296
303
|
| Microsoft Agent Framework | `pip install "agenticdome-python-sdk[microsoft]"` |
|
|
304
|
+
| Microsoft AutoGen AgentChat / Core (Python 3.10+) | `pip install "agenticdome-python-sdk[autogen]"` |
|
|
297
305
|
| Microsoft AI Foundry | `pip install "agenticdome-python-sdk[foundry]"` |
|
|
298
306
|
| OpenAI Agents SDK | `pip install "agenticdome-python-sdk[openai-agents]"` |
|
|
299
307
|
| Anthropic Claude Agent SDK | `pip install "agenticdome-python-sdk[claude]"` |
|
|
@@ -309,6 +317,12 @@ pip install agenticdome-python-sdk
|
|
|
309
317
|
|
|
310
318
|
Some adapters are dependency-light at import time: Google ADK, LlamaIndex, Bedrock, MCP, and Microsoft helpers can wrap local boundaries without forcing one exact runtime stack. Install the framework packages your application actually uses.
|
|
311
319
|
|
|
320
|
+
### Framework-version compatibility
|
|
321
|
+
|
|
322
|
+
AgenticDome supports framework versions only inside the range certified by the SDK Harness. When an upstream framework release appears, **Upgrade & Certify** keeps the existing certified version as the compatibility floor, tests the new release as the ceiling, and publishes an inclusive dependency range such as `framework>=floor,<=ceiling` only when both endpoints pass the adapter and firewall release gates. Multi-package integrations such as LangGraph/LangChain are also retested at their complete certified floor set.
|
|
323
|
+
|
|
324
|
+
This means upgrading support for the latest framework does not silently drop customers on the previously certified version. Versions below the displayed certified floor are not claimed as supported until they are tested. Customers managing framework dependencies themselves may install the core SDK without an extra, but their framework version must still be inside the certified range for a production support claim.
|
|
325
|
+
|
|
312
326
|
---
|
|
313
327
|
|
|
314
328
|
## Configuration
|
|
@@ -406,7 +420,7 @@ export AGENTICDOME_PRODUCTION_MODE="false" # production hardening (st
|
|
|
406
420
|
<details>
|
|
407
421
|
<summary><strong>Full configuration reference — per-adapter variables</strong></summary>
|
|
408
422
|
|
|
409
|
-
Every framework adapter exposes the same family of local hardening controls, prefixed per adapter: `AGENTICDOME_CREWAI_*`, `AGENTICDOME_PYDANTICAI_*`, `AGENTICDOME_LANGGRAPH_*`, `AGENTICDOME_MSAF_*` (Microsoft Agent Framework), `AGENTICDOME_FOUNDRY_*`, `AGENTICDOME_OPENAI_AGENTS_*`, `AGENTICDOME_CLAUDE_*`, `AGENTICDOME_SMOLAGENTS_*`, `AGENTICDOME_AGNO_*`, `AGENTICDOME_BEDROCK_*`, `AGENTICDOME_GOOGLE_ADK_*`, and `AGENTICDOME_MCP_*`.
|
|
423
|
+
Every framework adapter exposes the same family of local hardening controls, prefixed per adapter: `AGENTICDOME_CREWAI_*`, `AGENTICDOME_PYDANTICAI_*`, `AGENTICDOME_LANGGRAPH_*`, `AGENTICDOME_MSAF_*` (Microsoft Agent Framework), `AGENTICDOME_AUTOGEN_*`, `AGENTICDOME_FOUNDRY_*`, `AGENTICDOME_OPENAI_AGENTS_*`, `AGENTICDOME_CLAUDE_*`, `AGENTICDOME_SMOLAGENTS_*`, `AGENTICDOME_AGNO_*`, `AGENTICDOME_BEDROCK_*`, `AGENTICDOME_GOOGLE_ADK_*`, and `AGENTICDOME_MCP_*`.
|
|
410
424
|
|
|
411
425
|
**Common per-adapter pattern** (substitute the prefix for your adapter):
|
|
412
426
|
|
|
@@ -484,6 +498,7 @@ One table, one decision. Find your runtime, apply the required code action, and
|
|
|
484
498
|
| [PydanticAI](#pydanticai) | `agenticdome_sdk.pydantic` | Module where each `Agent(...)` and tool is constructed | `CyberSecFirewall(...)` + `create_hooks()`, `install_native_hooks(agent)`, or `attach_to_agent(agent)` | `@firewall.secure_tool(...)` with optional `tool_schema` validation |
|
|
485
499
|
| [LangGraph](#langgraph) | `agenticdome_sdk.langgraph` | Module where `StateGraph` or LangChain `create_agent()` is assembled | Add `input_node()` / `transition_node()` / `graph_transition_node()` / `output_node()`, or `as_langchain_middleware()` | `wrap_agent_node()`, `wrap_tool_node()`, `security_route()` for blocked edges |
|
|
486
500
|
| [Microsoft Agent Framework](#microsoft-agent-framework) | `agenticdome_sdk.microsoft_agent_framework` | Module where agents, workflows, tools, or middleware are declared | `create_middleware()`, `install_on_agent()`, or `run_agent_securely()` | `@firewall.secure_tool`, `wrap_tool_handler`, `secure_delegated_tool`, `wrap_delegated_tool_handler` |
|
|
501
|
+
| [Microsoft AutoGen](#microsoft-autogen) | `agenticdome_sdk.autogen` | AgentChat teams/Core runtimes; legacy 0.2 ConversableAgent loops | `wrap_team()`, `create_intervention_handler()`, `create_termination_condition()`, `attach_agentchat_agent()`, or `attach_conversable_agent()` | Core `FunctionCall` authorization plus inherited `wrap_tool_handler()` / `secure_tool()` |
|
|
487
502
|
| [Microsoft AI Foundry](#microsoft-ai-foundry) | `agenticdome_sdk.microsoft_ai_foundry` | Module handling Foundry runs, function calls, or client construction | `create_middleware()`, `install_on_client()`, or `run_secure()` | `wrap_tool_executor()`, `@firewall.secure_tool(...)`, `before_tool_call()`, delegation verifiers |
|
|
488
503
|
| [OpenAI Agents SDK](#openai-agents-sdk) | `agenticdome_sdk.openai_agents` | Module where `Agent`, `Runner.run(...)`, `@function_tool`, guardrails, or handoffs are declared | `run_agent_securely()`, `run_agent_stream_securely()`, `create_input_guardrail()`, `create_output_guardrail()` | `wrap_tool_handler()`, `wrap_delegated_tool_handler()`, `@firewall.secure_tool(...)`, handoff verifiers |
|
|
489
504
|
| [Claude Agent SDK](#claude-agent-sdk) | `agenticdome_sdk.claude` | Module constructing `ClaudeAgentOptions`, `ClaudeSDKClient`, SDK MCP tools, or `query()` | `install_on_options()` plus `run_client_securely()`, or `secure_query()` | Native `PreToolUse`/`PostToolUse` hooks, `wrap_tool_handler()`, and `secure_sdk_tool()` |
|
|
@@ -1013,6 +1028,108 @@ from agenticdome_sdk.microsoft_agent_framework import (
|
|
|
1013
1028
|
|
|
1014
1029
|
---
|
|
1015
1030
|
|
|
1031
|
+
### Microsoft AutoGen
|
|
1032
|
+
|
|
1033
|
+
AutoGen is Microsoft's open-source conversational multi-agent framework and is now community-managed in maintenance mode; Microsoft Agent Framework is the recommended successor for new systems. AgenticDome supports current AutoGen AgentChat/Core applications and existing legacy `ConversableAgent` deployments so teams can migrate without losing runtime enforcement.
|
|
1034
|
+
|
|
1035
|
+
```bash
|
|
1036
|
+
# AutoGen AgentChat requires Python 3.10+.
|
|
1037
|
+
pip install "agenticdome-python-sdk[autogen]"
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
**Protect a current AgentChat team** — the wrapper screens the initial task, every streamed team event, and final messages while retaining the underlying Team API:
|
|
1041
|
+
|
|
1042
|
+
```python
|
|
1043
|
+
from autogen_agentchat.teams import RoundRobinGroupChat
|
|
1044
|
+
from agenticdome_sdk.autogen import AgenticDomeAutoGenFirewall
|
|
1045
|
+
|
|
1046
|
+
firewall = AgenticDomeAutoGenFirewall()
|
|
1047
|
+
team = RoundRobinGroupChat([planner, researcher, payments_specialist], max_turns=12)
|
|
1048
|
+
secure_team = firewall.wrap_team(
|
|
1049
|
+
team,
|
|
1050
|
+
session_id="sess_prod_01J4X",
|
|
1051
|
+
agent_id="customer_operations_team",
|
|
1052
|
+
policy_context={"request_purpose": "customer_support"},
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
result = await secure_team.run(task=user_prompt)
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
**Authorize AutoGen Core tool traffic at the runtime boundary** — current AutoGen sends `FunctionCall` messages to tool agents, so the intervention handler is a stronger boundary than patching an individual assistant:
|
|
1059
|
+
|
|
1060
|
+
```python
|
|
1061
|
+
from autogen_core import SingleThreadedAgentRuntime
|
|
1062
|
+
|
|
1063
|
+
handler = firewall.create_intervention_handler(
|
|
1064
|
+
session_id="sess_prod_01J4X",
|
|
1065
|
+
agent_id="autogen_planner",
|
|
1066
|
+
)
|
|
1067
|
+
runtime = SingleThreadedAgentRuntime(intervention_handlers=[handler])
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
**Freeze a group chat on behavioral drift** — compose the AgenticDome condition with AutoGen's normal termination conditions:
|
|
1071
|
+
|
|
1072
|
+
```python
|
|
1073
|
+
agenticdome_stop = firewall.create_termination_condition(
|
|
1074
|
+
session_id="sess_prod_01J4X",
|
|
1075
|
+
agent_id="customer_operations_team",
|
|
1076
|
+
)
|
|
1077
|
+
team = RoundRobinGroupChat(
|
|
1078
|
+
[planner, researcher, payments_specialist],
|
|
1079
|
+
termination_condition=agenticdome_stop | normal_stop,
|
|
1080
|
+
max_turns=12,
|
|
1081
|
+
)
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
Family 2 policy receives a bounded rolling conversation window digest, participant lineage, semantic-deviation evaluation request, and tool-call frequency. A blocked cross-agent message or excessive tool rate freezes the local session, reports a trust incident, and advances revocation state for the emitting agent before an external action can run.
|
|
1085
|
+
|
|
1086
|
+
**Existing AutoGen 0.2 deployments** — attach to the legacy `ConversableAgent.send()`, `receive()`, `a_send()`, and `a_receive()` lifecycles:
|
|
1087
|
+
|
|
1088
|
+
Keep the customer's already-certified legacy AutoGen dependency in place and install the dependency-light base SDK (do not use the `[autogen]` extra, because that extra deliberately installs the current AgentChat release):
|
|
1089
|
+
|
|
1090
|
+
```bash
|
|
1091
|
+
pip install agenticdome-python-sdk
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
```python
|
|
1095
|
+
assistant = firewall.attach_conversable_agent(
|
|
1096
|
+
assistant,
|
|
1097
|
+
session_id="sess_prod_01J4X",
|
|
1098
|
+
agent_id="legacy_autogen_assistant",
|
|
1099
|
+
)
|
|
1100
|
+
user_proxy = firewall.attach_conversable_agent(
|
|
1101
|
+
user_proxy,
|
|
1102
|
+
session_id="sess_prod_01J4X",
|
|
1103
|
+
agent_id="legacy_autogen_user_proxy",
|
|
1104
|
+
)
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
Wrap side-effecting local tools as well; conversation screening does not replace authorization at the execution boundary:
|
|
1108
|
+
|
|
1109
|
+
```python
|
|
1110
|
+
secure_refund = firewall.wrap_tool_handler(
|
|
1111
|
+
tool_name="payments.refund.create",
|
|
1112
|
+
tool_platform="payments",
|
|
1113
|
+
handler=raw_refund,
|
|
1114
|
+
session_id="sess_prod_01J4X",
|
|
1115
|
+
agent_id="payments_specialist",
|
|
1116
|
+
)
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
```bash
|
|
1120
|
+
export AGENTICDOME_PLATFORM="autogen"
|
|
1121
|
+
export AGENTICDOME_PRODUCTION_MODE="true"
|
|
1122
|
+
export AGENTICDOME_REQUIRE_STABLE_SESSION_ID_IN_PROD="true"
|
|
1123
|
+
export AGENTICDOME_AUTOGEN_CONVERSATION_WINDOW="12"
|
|
1124
|
+
export AGENTICDOME_AUTOGEN_MAX_TOOL_CALLS_PER_WINDOW="8"
|
|
1125
|
+
export AGENTICDOME_AUTOGEN_FREEZE_ON_BLOCK="true"
|
|
1126
|
+
export AGENTICDOME_AUTOGEN_REVOKE_ON_FREEZE="true"
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
Official references: [AutoGen project status and migration guidance](https://github.com/microsoft/autogen) · [AgentChat teams](https://microsoft.github.io/autogen/stable/reference/python/autogen_agentchat.teams.html) · [Core intervention handlers](https://microsoft.github.io/autogen/dev/user-guide/core-user-guide/cookbook/tool-use-with-intervention.html) · [Legacy 0.2 conversational agents](https://microsoft.github.io/autogen/0.2/docs/Use-Cases/agent_chat/)
|
|
1130
|
+
|
|
1131
|
+
---
|
|
1132
|
+
|
|
1016
1133
|
### Microsoft AI Foundry
|
|
1017
1134
|
|
|
1018
1135
|
For services that call Foundry agents, handle function-call requests from Foundry, execute local function tools, or use `FoundryChatClient` with local tools.
|
|
@@ -2366,7 +2483,7 @@ source .venv/bin/activate
|
|
|
2366
2483
|
|
|
2367
2484
|
python -m pip install --upgrade pip setuptools wheel
|
|
2368
2485
|
python -m pip install -e ".[dev]"
|
|
2369
|
-
python -m pip install -e ".[crewai,pydanticai,langgraph,microsoft,foundry,agno,openai-agents,mcp,bedrock,google-adk,llamaindex,redis]"
|
|
2486
|
+
python -m pip install -e ".[crewai,pydanticai,langgraph,microsoft,autogen,foundry,agno,openai-agents,claude,smolagents,mcp,bedrock,google-adk,llamaindex,redis]"
|
|
2370
2487
|
|
|
2371
2488
|
python -m pytest -q
|
|
2372
2489
|
rm -rf build dist *.egg-info agenticdome_sdk.egg-info agenticdome_python_sdk.egg-info
|
|
@@ -2389,10 +2506,12 @@ python -m pytest -q tests/test_langgraph_integration.py
|
|
|
2389
2506
|
| :--- | :--- | :--- |
|
|
2390
2507
|
| Core SDK client | `python -m pytest -q tests/test_client.py` | Request validation, headers, guardrail calls, A2A/MCP JSON-RPC calls, Mesh DLP, HTTP errors, JSON handling |
|
|
2391
2508
|
| Package contract | `python -m pytest -q tests/test_packaging_contract.py` | `pyproject.toml` metadata, legacy `setup.py` shim, public exports, manifest hygiene, ignored build artifacts, documented extras |
|
|
2509
|
+
| Attack demos | `python -m pytest -q tests/test_attack_demo.py` | Offline vulnerable-vs-protected CLI coverage, including AutoGen, Claude Agent SDK, and Hugging Face smolagents |
|
|
2392
2510
|
| CrewAI | `python -m pytest -q tests/test_crewai_integration.py` | Prompt/tool hooks, handoff token injection, specialist verification, output redaction, schema checks, rate limits, retries, streaming DLP |
|
|
2393
2511
|
| PydanticAI | `python -m pytest -q tests/test_pydanticai_integration.py` | Agent hooks, secure tools, sanitized arguments, token-store fallback, production session enforcement, rate limits, retries, streaming output |
|
|
2394
2512
|
| LangGraph / LangChain | `python -m pytest -q tests/test_langgraph_integration.py` | Graph input, transition, tool, retrieval, middleware, security routing, token consumption, output DLP, streaming events |
|
|
2395
2513
|
| Microsoft Agent Framework | `python -m pytest -q tests/test_microsoft_agent_framework_integration.py` | Tool/run boundaries, delegated tool verification, middleware install helpers, identity context, Copilot enforcement hooks, streaming output |
|
|
2514
|
+
| Microsoft AutoGen | `python -m pytest -q tests/test_autogen_integration.py` | Current AgentChat team/Core interception, legacy send/receive hooks, rolling Family 2 context, session freeze, trust incident and revocation escalation |
|
|
2396
2515
|
| Microsoft AI Foundry | `python -m pytest -q tests/test_microsoft_ai_foundry_integration.py` | Prompt threat contracts, local tool executors, run boundaries, bearer/API-key configuration, delegated execution, circuit breaker, stream DLP |
|
|
2397
2516
|
| OpenAI Agents SDK | `python -m pytest -q tests/test_openai_agents_integration.py` | Runner wrappers, guardrail helpers, function-tool wrappers, handoff/delegated tools, HMAC token storage, schema checks, retries, streaming output |
|
|
2398
2517
|
| Claude Agent SDK | `python -m pytest -q tests/test_claude_integration.py` | Native prompt/tool hooks, tool-output replacement, secure query responses, decision-token binding and one-time consumption |
|
|
@@ -2417,7 +2536,7 @@ python -m twine check dist/*
|
|
|
2417
2536
|
**Full offline release gate** across all supported Python integrations:
|
|
2418
2537
|
|
|
2419
2538
|
```bash
|
|
2420
|
-
python -m pip install -e ".[dev,crewai,pydanticai,langgraph,microsoft,foundry,agno,openai-agents,mcp,bedrock,google-adk,llamaindex,redis]"
|
|
2539
|
+
python -m pip install -e ".[dev,crewai,pydanticai,langgraph,microsoft,autogen,foundry,agno,openai-agents,claude,smolagents,mcp,bedrock,google-adk,llamaindex,redis]"
|
|
2421
2540
|
python -m pytest -q
|
|
2422
2541
|
rm -rf build dist *.egg-info agenticdome_sdk.egg-info agenticdome_python_sdk.egg-info
|
|
2423
2542
|
python -m build
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
agenticdome_python_sdk-1.2.
|
|
1
|
+
agenticdome_python_sdk-1.2.3.dist-info/licenses/LICENSE,sha256=lqAH8G9tU2WPK9fzrnM_QMd4XUrh9fsmPqKE_hniKpM,718
|
|
2
2
|
agenticdome_sdk/__init__.py,sha256=6eOHJkY_Ir51dRKTktObXS40PjUsHrWMEQ2V3N0ItN4,576
|
|
3
3
|
agenticdome_sdk/_framework_firewall.py,sha256=XJaKgDlVFfZJXVg1vL8jQOZDH05g8P9GQseh8J22p4M,27860
|
|
4
4
|
agenticdome_sdk/agno.py,sha256=3gbc5URNTAHyNVAaAH882CpQpMecTv0R6S0CNMDOgos,60686
|
|
5
|
+
agenticdome_sdk/autogen.py,sha256=0NAqCxk9zTyRZX7LnqqdT9cSzjbAJjQVgz6aq9QWy0Q,29015
|
|
5
6
|
agenticdome_sdk/aws_bedrock.py,sha256=Z1Rcbps7VgvETmq_wrUbIvg6lJxsoe7YJEPZYkBKr80,69498
|
|
6
7
|
agenticdome_sdk/claude.py,sha256=LEmfIAXOkZlbE_XISDHagze2JiDlRUA_j776ntP4QwM,17454
|
|
7
8
|
agenticdome_sdk/client.py,sha256=rRFqW5zXVDYGqDrchy3D-HxRaDINttcgYu8VRQXnceU,48658
|
|
@@ -18,7 +19,7 @@ agenticdome_sdk/proof.py,sha256=ECKc14xSE0V1HHmcpZjfVz8-Q2H_fooah3BfdblFV8M,2878
|
|
|
18
19
|
agenticdome_sdk/pydantic.py,sha256=7R6X0JgPIMLcWO682wcpN0X8dSMVEiwvVc4ydUN111s,54882
|
|
19
20
|
agenticdome_sdk/scenarios.py,sha256=QROC_JWKwub5AdpP9pLXdJCpotEACkF-qgKAnDAo8XA,7882
|
|
20
21
|
agenticdome_sdk/smolagents.py,sha256=j51nHazdFvA2DNRv6mibKKcEkZvw__xg6bjPUrhMKuk,19092
|
|
21
|
-
agenticdome_python_sdk-1.2.
|
|
22
|
-
agenticdome_python_sdk-1.2.
|
|
23
|
-
agenticdome_python_sdk-1.2.
|
|
24
|
-
agenticdome_python_sdk-1.2.
|
|
22
|
+
agenticdome_python_sdk-1.2.3.dist-info/METADATA,sha256=RthBXIsCPHzc1iYbENsoCbtmZfZO7xg71Gw-BDqEJRg,128670
|
|
23
|
+
agenticdome_python_sdk-1.2.3.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
24
|
+
agenticdome_python_sdk-1.2.3.dist-info/top_level.txt,sha256=LZbbjXco5mqDrGwlTJpIKI5Sp6R_njzHHjExxAs9c3s,16
|
|
25
|
+
agenticdome_python_sdk-1.2.3.dist-info/RECORD,,
|
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import copy
|
|
4
|
+
import hashlib
|
|
5
|
+
import inspect
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
from collections import defaultdict, deque
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from threading import Lock
|
|
12
|
+
from types import MethodType
|
|
13
|
+
from typing import Any, AsyncIterator, Callable, Deque, Dict, Iterable, List, Optional
|
|
14
|
+
|
|
15
|
+
from ._framework_firewall import DecisionTokenStore, FrameworkFirewallBase, FrameworkFirewallConfig
|
|
16
|
+
from .client import AgentGuardClient
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger("agenticdome.autogen")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _env(name: str, default: str = "") -> str:
|
|
23
|
+
return os.getenv(name, os.getenv(name.replace("AGENTICDOME", "AgenticDome"), default))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _env_bool(name: str, default: bool) -> bool:
|
|
27
|
+
value = _env(name)
|
|
28
|
+
return default if value == "" else value.strip().lower() in {"1", "true", "yes", "y", "on"}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _env_int(name: str, default: int) -> int:
|
|
32
|
+
try:
|
|
33
|
+
return int(_env(name, str(default)))
|
|
34
|
+
except (TypeError, ValueError):
|
|
35
|
+
return default
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _env_float(name: str, default: float) -> float:
|
|
39
|
+
try:
|
|
40
|
+
return float(_env(name, str(default)))
|
|
41
|
+
except (TypeError, ValueError):
|
|
42
|
+
return default
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class FirewallConfig(FrameworkFirewallConfig):
|
|
47
|
+
platform: str = "autogen"
|
|
48
|
+
agent_id: str = "autogen_agent"
|
|
49
|
+
default_tool_platform: str = "autogen"
|
|
50
|
+
redis_key_prefix: str = "AgenticDome:autogen:handoff"
|
|
51
|
+
conversation_window_messages: int = 12
|
|
52
|
+
max_tool_calls_per_window: int = 8
|
|
53
|
+
freeze_on_policy_block: bool = True
|
|
54
|
+
revoke_agent_on_freeze: bool = True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def load_config() -> FirewallConfig:
|
|
58
|
+
return FirewallConfig(
|
|
59
|
+
api_base=_env("AGENTICDOME_API_BASE").rstrip("/"),
|
|
60
|
+
api_key=_env("AGENTICDOME_API_KEY"),
|
|
61
|
+
tenant_id=_env("AGENTICDOME_TENANT_ID"),
|
|
62
|
+
platform=_env("AGENTICDOME_PLATFORM", "autogen"),
|
|
63
|
+
agent_id=_env("AGENTICDOME_AUTOGEN_AGENT_ID", "autogen_agent"),
|
|
64
|
+
default_tool_platform=_env("AGENTICDOME_DEFAULT_TOOL_PLATFORM", "autogen"),
|
|
65
|
+
timeout_s=_env_int("AGENTICDOME_TIMEOUT_S", 20),
|
|
66
|
+
fail_closed=_env_bool("AGENTICDOME_FAIL_CLOSED", True),
|
|
67
|
+
production_mode=_env_bool("AGENTICDOME_PRODUCTION_MODE", False),
|
|
68
|
+
require_explicit_session_id=_env_bool("AGENTICDOME_REQUIRE_SESSION_ID", False),
|
|
69
|
+
require_stable_session_id_in_prod=_env_bool("AGENTICDOME_REQUIRE_STABLE_SESSION_ID_IN_PROD", True),
|
|
70
|
+
redact_pii=_env_bool("AGENTICDOME_REDACT_PII", True),
|
|
71
|
+
redact_secrets=_env_bool("AGENTICDOME_REDACT_SECRETS", True),
|
|
72
|
+
block_on_sensitive_output=_env_bool("AGENTICDOME_BLOCK_ON_SENSITIVE_OUTPUT", False),
|
|
73
|
+
handoff_token_ttl_s=_env_int("AGENTICDOME_HANDOFF_TOKEN_TTL_S", 900),
|
|
74
|
+
redis_url=_env("AGENTICDOME_REDIS_URL").strip(),
|
|
75
|
+
redis_key_prefix=_env("AGENTICDOME_REDIS_KEY_PREFIX", "AgenticDome:autogen:handoff"),
|
|
76
|
+
token_hmac_secret=_env("AGENTICDOME_TOKEN_HMAC_SECRET"),
|
|
77
|
+
max_input_chars=_env_int("AGENTICDOME_AUTOGEN_MAX_INPUT_CHARS", 50_000),
|
|
78
|
+
max_output_chars=_env_int("AGENTICDOME_AUTOGEN_MAX_OUTPUT_CHARS", 100_000),
|
|
79
|
+
max_tool_arg_chars=_env_int("AGENTICDOME_AUTOGEN_MAX_TOOL_ARG_CHARS", 20_000),
|
|
80
|
+
streaming_buffer_chars=_env_int("AGENTICDOME_AUTOGEN_STREAMING_BUFFER_CHARS", 4_000),
|
|
81
|
+
rate_limit_per_minute=_env_int("AGENTICDOME_AUTOGEN_RATE_LIMIT_PER_MINUTE", 0),
|
|
82
|
+
retry_attempts=_env_int("AGENTICDOME_AUTOGEN_RETRY_ATTEMPTS", 2),
|
|
83
|
+
retry_backoff_s=_env_float("AGENTICDOME_AUTOGEN_RETRY_BACKOFF_S", 0.25),
|
|
84
|
+
circuit_breaker_failures=_env_int("AGENTICDOME_AUTOGEN_CIRCUIT_BREAKER_FAILURES", 5),
|
|
85
|
+
circuit_breaker_reset_s=_env_int("AGENTICDOME_AUTOGEN_CIRCUIT_BREAKER_RESET_S", 60),
|
|
86
|
+
audit_logging=_env_bool("AGENTICDOME_AUTOGEN_AUDIT_LOGGING", True),
|
|
87
|
+
otel_enabled=_env_bool("AGENTICDOME_AUTOGEN_OTEL_ENABLED", True),
|
|
88
|
+
emergency_block_tools=_env("AGENTICDOME_AUTOGEN_EMERGENCY_BLOCK_TOOLS"),
|
|
89
|
+
emergency_block_agents=_env("AGENTICDOME_AUTOGEN_EMERGENCY_BLOCK_AGENTS"),
|
|
90
|
+
strict_delegated_execution=_env_bool("AGENTICDOME_AUTOGEN_STRICT_DELEGATED_EXECUTION", True),
|
|
91
|
+
scan_code_expressions=_env_bool("AGENTICDOME_AUTOGEN_SCAN_CODE", True),
|
|
92
|
+
report_incidents=_env_bool("AGENTICDOME_REPORT_INCIDENTS", True),
|
|
93
|
+
blocked_incident_severity=_env("AGENTICDOME_BLOCKED_INCIDENT_SEVERITY", "high"),
|
|
94
|
+
conversation_window_messages=_env_int("AGENTICDOME_AUTOGEN_CONVERSATION_WINDOW", 12),
|
|
95
|
+
max_tool_calls_per_window=_env_int("AGENTICDOME_AUTOGEN_MAX_TOOL_CALLS_PER_WINDOW", 8),
|
|
96
|
+
freeze_on_policy_block=_env_bool("AGENTICDOME_AUTOGEN_FREEZE_ON_BLOCK", True),
|
|
97
|
+
revoke_agent_on_freeze=_env_bool("AGENTICDOME_AUTOGEN_REVOKE_ON_FREEZE", True),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class AutoGenFirewallError(RuntimeError):
|
|
102
|
+
"""Base error for the Microsoft AutoGen adapter."""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class AutoGenFirewallDenied(AutoGenFirewallError):
|
|
106
|
+
"""Raised when an AutoGen message, tool, handoff, or team run is denied."""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class AutoGenFirewallConfigurationError(AutoGenFirewallError):
|
|
110
|
+
"""Raised when AgenticDome runtime configuration is incomplete."""
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
ToolBlocked = AutoGenFirewallDenied
|
|
114
|
+
FirewallMisconfigured = AutoGenFirewallConfigurationError
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _agent_name(value: Any, fallback: str) -> str:
|
|
118
|
+
if value is None:
|
|
119
|
+
return fallback
|
|
120
|
+
for key in ("name", "id", "agent_id", "type"):
|
|
121
|
+
candidate = value.get(key) if isinstance(value, dict) else getattr(value, key, None)
|
|
122
|
+
if candidate:
|
|
123
|
+
return str(candidate)
|
|
124
|
+
return fallback
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _content(value: Any) -> str:
|
|
128
|
+
if value is None:
|
|
129
|
+
return ""
|
|
130
|
+
if isinstance(value, str):
|
|
131
|
+
return value
|
|
132
|
+
if isinstance(value, dict):
|
|
133
|
+
for key in ("content", "text", "message", "task", "arguments"):
|
|
134
|
+
if key in value and value[key] is not None:
|
|
135
|
+
return _content(value[key])
|
|
136
|
+
return json.dumps(value, sort_keys=True, default=str)
|
|
137
|
+
if isinstance(value, (list, tuple)):
|
|
138
|
+
return "\n".join(filter(None, (_content(item) for item in value)))
|
|
139
|
+
for key in ("content", "text", "message", "task", "arguments"):
|
|
140
|
+
candidate = getattr(value, key, None)
|
|
141
|
+
if candidate is not None:
|
|
142
|
+
return _content(candidate)
|
|
143
|
+
return str(value)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _replace_content(value: Any, content: str) -> Any:
|
|
147
|
+
if isinstance(value, str):
|
|
148
|
+
return content
|
|
149
|
+
if isinstance(value, dict):
|
|
150
|
+
updated = dict(value)
|
|
151
|
+
key = next((item for item in ("content", "text", "message", "task") if item in updated), "content")
|
|
152
|
+
updated[key] = content
|
|
153
|
+
return updated
|
|
154
|
+
model_copy = getattr(value, "model_copy", None)
|
|
155
|
+
if callable(model_copy) and hasattr(value, "content"):
|
|
156
|
+
try:
|
|
157
|
+
return model_copy(update={"content": content})
|
|
158
|
+
except Exception:
|
|
159
|
+
pass
|
|
160
|
+
if hasattr(value, "content"):
|
|
161
|
+
try:
|
|
162
|
+
updated = copy.copy(value)
|
|
163
|
+
setattr(updated, "content", content)
|
|
164
|
+
return updated
|
|
165
|
+
except Exception:
|
|
166
|
+
pass
|
|
167
|
+
return value
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class SecureAutoGenTeam:
|
|
171
|
+
"""Dependency-light proxy for current AutoGen AgentChat Team.run/run_stream."""
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
team: Any,
|
|
176
|
+
firewall: "AgenticDomeAutoGenFirewall",
|
|
177
|
+
*,
|
|
178
|
+
session_id: str,
|
|
179
|
+
agent_id: str,
|
|
180
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
181
|
+
) -> None:
|
|
182
|
+
self._team = team
|
|
183
|
+
self._firewall = firewall
|
|
184
|
+
self._session_id = session_id
|
|
185
|
+
self._agent_id = agent_id
|
|
186
|
+
self._policy_context = dict(policy_context or {})
|
|
187
|
+
|
|
188
|
+
def __getattr__(self, name: str) -> Any:
|
|
189
|
+
return getattr(self._team, name)
|
|
190
|
+
|
|
191
|
+
async def run(self, *args: Any, **kwargs: Any) -> Any:
|
|
192
|
+
task = kwargs.get("task", args[0] if args else None)
|
|
193
|
+
if task is not None:
|
|
194
|
+
secured = await self._firewall.ainspect_message(
|
|
195
|
+
task,
|
|
196
|
+
session_id=self._session_id,
|
|
197
|
+
sender_agent_id="user",
|
|
198
|
+
recipient_agent_id=self._agent_id,
|
|
199
|
+
direction="team_input",
|
|
200
|
+
policy_context=self._policy_context,
|
|
201
|
+
)
|
|
202
|
+
if "task" in kwargs:
|
|
203
|
+
kwargs["task"] = secured
|
|
204
|
+
elif args:
|
|
205
|
+
args = (secured, *args[1:])
|
|
206
|
+
result = await self._team.run(*args, **kwargs)
|
|
207
|
+
return await self._firewall.areview_team_result(
|
|
208
|
+
result,
|
|
209
|
+
session_id=self._session_id,
|
|
210
|
+
agent_id=self._agent_id,
|
|
211
|
+
policy_context=self._policy_context,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
async def run_stream(self, *args: Any, **kwargs: Any) -> AsyncIterator[Any]:
|
|
215
|
+
task = kwargs.get("task", args[0] if args else None)
|
|
216
|
+
if task is not None:
|
|
217
|
+
secured = await self._firewall.ainspect_message(
|
|
218
|
+
task,
|
|
219
|
+
session_id=self._session_id,
|
|
220
|
+
sender_agent_id="user",
|
|
221
|
+
recipient_agent_id=self._agent_id,
|
|
222
|
+
direction="team_input",
|
|
223
|
+
policy_context=self._policy_context,
|
|
224
|
+
)
|
|
225
|
+
if "task" in kwargs:
|
|
226
|
+
kwargs["task"] = secured
|
|
227
|
+
elif args:
|
|
228
|
+
args = (secured, *args[1:])
|
|
229
|
+
async for event in self._team.run_stream(*args, **kwargs):
|
|
230
|
+
yield await self._firewall.ainspect_message(
|
|
231
|
+
event,
|
|
232
|
+
session_id=self._session_id,
|
|
233
|
+
sender_agent_id=_agent_name(event, self._agent_id),
|
|
234
|
+
recipient_agent_id="team_output",
|
|
235
|
+
direction="team_stream",
|
|
236
|
+
policy_context=self._policy_context,
|
|
237
|
+
sanitize=True,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class AgenticDomeAutoGenFirewall(FrameworkFirewallBase):
|
|
242
|
+
"""Native policy boundaries for AutoGen AgentChat/Core and legacy ConversableAgent."""
|
|
243
|
+
|
|
244
|
+
def __init__(
|
|
245
|
+
self,
|
|
246
|
+
config: Optional[FirewallConfig] = None,
|
|
247
|
+
*,
|
|
248
|
+
client: Optional[AgentGuardClient] = None,
|
|
249
|
+
token_store: Optional[DecisionTokenStore] = None,
|
|
250
|
+
) -> None:
|
|
251
|
+
resolved = config or load_config()
|
|
252
|
+
super().__init__(
|
|
253
|
+
resolved,
|
|
254
|
+
client=client,
|
|
255
|
+
token_store=token_store,
|
|
256
|
+
denied_error=AutoGenFirewallDenied,
|
|
257
|
+
configuration_error=AutoGenFirewallConfigurationError,
|
|
258
|
+
label="Microsoft AutoGen",
|
|
259
|
+
logger=logger,
|
|
260
|
+
)
|
|
261
|
+
self.config: FirewallConfig = resolved
|
|
262
|
+
self._conversation_lock = Lock()
|
|
263
|
+
self._conversation_windows: Dict[str, Deque[Dict[str, Any]]] = defaultdict(
|
|
264
|
+
lambda: deque(maxlen=max(1, self.config.conversation_window_messages))
|
|
265
|
+
)
|
|
266
|
+
self._frozen_sessions: Dict[str, str] = {}
|
|
267
|
+
|
|
268
|
+
authorize_direct_tool_call = FrameworkFirewallBase.authorize_tool_call
|
|
269
|
+
|
|
270
|
+
def is_session_frozen(self, session_id: str) -> bool:
|
|
271
|
+
with self._conversation_lock:
|
|
272
|
+
return session_id in self._frozen_sessions
|
|
273
|
+
|
|
274
|
+
def frozen_reason(self, session_id: str) -> Optional[str]:
|
|
275
|
+
with self._conversation_lock:
|
|
276
|
+
return self._frozen_sessions.get(session_id)
|
|
277
|
+
|
|
278
|
+
def unfreeze_session(self, session_id: str) -> None:
|
|
279
|
+
with self._conversation_lock:
|
|
280
|
+
self._frozen_sessions.pop(session_id, None)
|
|
281
|
+
self._conversation_windows.pop(session_id, None)
|
|
282
|
+
|
|
283
|
+
def freeze_session(self, session_id: str, *, agent_id: str, reason: str) -> None:
|
|
284
|
+
with self._conversation_lock:
|
|
285
|
+
self._frozen_sessions[session_id] = reason
|
|
286
|
+
self._audit("conversation_frozen", session_id=session_id, agent_id=agent_id, reason=reason)
|
|
287
|
+
if self.config.report_incidents and hasattr(self.client, "report_incident"):
|
|
288
|
+
try:
|
|
289
|
+
self._client_call_sync(
|
|
290
|
+
self.client.report_incident,
|
|
291
|
+
agent_id=agent_id,
|
|
292
|
+
incident_type="autogen_conversation_policy_block",
|
|
293
|
+
severity=self.config.blocked_incident_severity,
|
|
294
|
+
details=reason,
|
|
295
|
+
platform=self.config.platform,
|
|
296
|
+
)
|
|
297
|
+
except Exception as exc:
|
|
298
|
+
logger.warning("AutoGen incident reporting failed after enforcement: %s", exc)
|
|
299
|
+
if self.config.revoke_agent_on_freeze and hasattr(self.client, "revoke_decision_token"):
|
|
300
|
+
try:
|
|
301
|
+
self._client_call_sync(
|
|
302
|
+
self.client.revoke_decision_token,
|
|
303
|
+
agent_id=agent_id,
|
|
304
|
+
reason=f"AutoGen session {session_id} frozen: {reason}",
|
|
305
|
+
)
|
|
306
|
+
except Exception as exc:
|
|
307
|
+
logger.warning("AutoGen revocation-epoch advance failed after enforcement: %s", exc)
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def _is_tool_event(message: Any) -> bool:
|
|
311
|
+
name = type(message).__name__.lower()
|
|
312
|
+
if any(marker in name for marker in ("functioncall", "toolcall", "codeexecution")):
|
|
313
|
+
return True
|
|
314
|
+
if isinstance(message, dict):
|
|
315
|
+
return bool(message.get("tool_name") or message.get("function_call") or message.get("tool_calls"))
|
|
316
|
+
return bool(getattr(message, "name", None) and getattr(message, "arguments", None) is not None)
|
|
317
|
+
|
|
318
|
+
def _record_event(
|
|
319
|
+
self,
|
|
320
|
+
*,
|
|
321
|
+
session_id: str,
|
|
322
|
+
sender_agent_id: str,
|
|
323
|
+
recipient_agent_id: str,
|
|
324
|
+
direction: str,
|
|
325
|
+
text: str,
|
|
326
|
+
tool_event: bool,
|
|
327
|
+
) -> Dict[str, Any]:
|
|
328
|
+
event = {
|
|
329
|
+
"sender": sender_agent_id,
|
|
330
|
+
"recipient": recipient_agent_id,
|
|
331
|
+
"direction": direction,
|
|
332
|
+
"text": text,
|
|
333
|
+
"tool_event": tool_event,
|
|
334
|
+
}
|
|
335
|
+
with self._conversation_lock:
|
|
336
|
+
window = self._conversation_windows[session_id]
|
|
337
|
+
window.append(event)
|
|
338
|
+
snapshot = list(window)
|
|
339
|
+
tool_calls = sum(1 for item in snapshot if item["tool_event"])
|
|
340
|
+
digest = hashlib.sha256(
|
|
341
|
+
json.dumps(snapshot, sort_keys=True, separators=(",", ":"), default=str).encode()
|
|
342
|
+
).hexdigest()
|
|
343
|
+
return {
|
|
344
|
+
"family": 2,
|
|
345
|
+
"family_name": "multi_agent_behavioral_trust",
|
|
346
|
+
"conversation_window_size": len(snapshot),
|
|
347
|
+
"conversation_window_limit": max(1, self.config.conversation_window_messages),
|
|
348
|
+
"tool_calls_in_window": tool_calls,
|
|
349
|
+
"tool_call_limit": max(0, self.config.max_tool_calls_per_window),
|
|
350
|
+
"conversation_digest": digest,
|
|
351
|
+
"conversation_participants": sorted(
|
|
352
|
+
{item["sender"] for item in snapshot} | {item["recipient"] for item in snapshot}
|
|
353
|
+
),
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
def inspect_message(
|
|
357
|
+
self,
|
|
358
|
+
message: Any,
|
|
359
|
+
*,
|
|
360
|
+
session_id: str,
|
|
361
|
+
sender_agent_id: str,
|
|
362
|
+
recipient_agent_id: str,
|
|
363
|
+
direction: str,
|
|
364
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
365
|
+
sanitize: bool = True,
|
|
366
|
+
) -> Any:
|
|
367
|
+
if self.is_session_frozen(session_id):
|
|
368
|
+
raise AutoGenFirewallDenied(
|
|
369
|
+
f"AgenticDome froze AutoGen session {session_id}: {self.frozen_reason(session_id)}"
|
|
370
|
+
)
|
|
371
|
+
text = _content(message)
|
|
372
|
+
metrics = self._record_event(
|
|
373
|
+
session_id=session_id,
|
|
374
|
+
sender_agent_id=sender_agent_id,
|
|
375
|
+
recipient_agent_id=recipient_agent_id,
|
|
376
|
+
direction=direction,
|
|
377
|
+
text=text,
|
|
378
|
+
tool_event=self._is_tool_event(message),
|
|
379
|
+
)
|
|
380
|
+
context = {
|
|
381
|
+
**dict(policy_context or {}),
|
|
382
|
+
**metrics,
|
|
383
|
+
"source_agent_id": sender_agent_id,
|
|
384
|
+
"target_agent_id": recipient_agent_id,
|
|
385
|
+
"conversation_direction": direction,
|
|
386
|
+
"semantic_deviation_evaluation": "server_side",
|
|
387
|
+
}
|
|
388
|
+
if metrics["tool_call_limit"] and metrics["tool_calls_in_window"] > metrics["tool_call_limit"]:
|
|
389
|
+
reason = "AutoGen tool-call frequency exceeded the certified rolling-window limit."
|
|
390
|
+
self.freeze_session(session_id, agent_id=sender_agent_id, reason=reason)
|
|
391
|
+
raise AutoGenFirewallDenied(reason)
|
|
392
|
+
try:
|
|
393
|
+
self.screen_input(
|
|
394
|
+
session_id=session_id,
|
|
395
|
+
agent_id=recipient_agent_id,
|
|
396
|
+
text=text,
|
|
397
|
+
policy_context=context,
|
|
398
|
+
)
|
|
399
|
+
if not sanitize or text == "":
|
|
400
|
+
return message
|
|
401
|
+
reviewed = self.sanitize_output(
|
|
402
|
+
session_id=session_id,
|
|
403
|
+
agent_id=sender_agent_id,
|
|
404
|
+
text=text,
|
|
405
|
+
policy_context=context,
|
|
406
|
+
)
|
|
407
|
+
return _replace_content(message, reviewed)
|
|
408
|
+
except AutoGenFirewallDenied as exc:
|
|
409
|
+
if self.config.freeze_on_policy_block:
|
|
410
|
+
self.freeze_session(session_id, agent_id=sender_agent_id, reason=str(exc))
|
|
411
|
+
raise
|
|
412
|
+
|
|
413
|
+
async def ainspect_message(self, message: Any, **kwargs: Any) -> Any:
|
|
414
|
+
# AgentGuardClient is intentionally synchronous. Keeping one enforcement
|
|
415
|
+
# path here avoids ordering races between consecutive AutoGen team events.
|
|
416
|
+
return self.inspect_message(message, **kwargs)
|
|
417
|
+
|
|
418
|
+
def wrap_team(
|
|
419
|
+
self,
|
|
420
|
+
team: Any,
|
|
421
|
+
*,
|
|
422
|
+
session_id: Optional[str] = None,
|
|
423
|
+
agent_id: Optional[str] = None,
|
|
424
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
425
|
+
) -> SecureAutoGenTeam:
|
|
426
|
+
sid = self.session_id(session_id, team)
|
|
427
|
+
aid = agent_id or _agent_name(team, self.config.agent_id)
|
|
428
|
+
return SecureAutoGenTeam(team, self, session_id=sid, agent_id=aid, policy_context=policy_context)
|
|
429
|
+
|
|
430
|
+
async def areview_team_result(
|
|
431
|
+
self,
|
|
432
|
+
result: Any,
|
|
433
|
+
*,
|
|
434
|
+
session_id: str,
|
|
435
|
+
agent_id: str,
|
|
436
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
437
|
+
) -> Any:
|
|
438
|
+
messages = getattr(result, "messages", None)
|
|
439
|
+
if not isinstance(messages, list):
|
|
440
|
+
return await self.ainspect_message(
|
|
441
|
+
result,
|
|
442
|
+
session_id=session_id,
|
|
443
|
+
sender_agent_id=agent_id,
|
|
444
|
+
recipient_agent_id="application",
|
|
445
|
+
direction="team_output",
|
|
446
|
+
policy_context=policy_context,
|
|
447
|
+
sanitize=True,
|
|
448
|
+
)
|
|
449
|
+
secured = []
|
|
450
|
+
for message in messages:
|
|
451
|
+
secured.append(
|
|
452
|
+
await self.ainspect_message(
|
|
453
|
+
message,
|
|
454
|
+
session_id=session_id,
|
|
455
|
+
sender_agent_id=_agent_name(message, agent_id),
|
|
456
|
+
recipient_agent_id="application",
|
|
457
|
+
direction="team_output",
|
|
458
|
+
policy_context=policy_context,
|
|
459
|
+
sanitize=True,
|
|
460
|
+
)
|
|
461
|
+
)
|
|
462
|
+
try:
|
|
463
|
+
updated = copy.copy(result)
|
|
464
|
+
updated.messages = secured
|
|
465
|
+
return updated
|
|
466
|
+
except Exception:
|
|
467
|
+
return result
|
|
468
|
+
|
|
469
|
+
def _attach_method(
|
|
470
|
+
self,
|
|
471
|
+
agent: Any,
|
|
472
|
+
method_name: str,
|
|
473
|
+
*,
|
|
474
|
+
session_id: str,
|
|
475
|
+
agent_id: str,
|
|
476
|
+
direction: str,
|
|
477
|
+
policy_context: Optional[Dict[str, Any]],
|
|
478
|
+
) -> bool:
|
|
479
|
+
original = getattr(agent, method_name, None)
|
|
480
|
+
if not callable(original):
|
|
481
|
+
return False
|
|
482
|
+
marker = f"_agenticdome_original_{method_name}"
|
|
483
|
+
if hasattr(agent, marker):
|
|
484
|
+
return False
|
|
485
|
+
setattr(agent, marker, original)
|
|
486
|
+
is_async = inspect.iscoroutinefunction(original)
|
|
487
|
+
|
|
488
|
+
async def async_wrapper(_agent: Any, message: Any, *args: Any, **kwargs: Any) -> Any:
|
|
489
|
+
peer = args[0] if args else kwargs.get("recipient") or kwargs.get("sender")
|
|
490
|
+
peer_id = _agent_name(peer, "autogen_peer")
|
|
491
|
+
sender, recipient = (agent_id, peer_id) if direction == "send" else (peer_id, agent_id)
|
|
492
|
+
secured = await self.ainspect_message(
|
|
493
|
+
message,
|
|
494
|
+
session_id=session_id,
|
|
495
|
+
sender_agent_id=sender,
|
|
496
|
+
recipient_agent_id=recipient,
|
|
497
|
+
direction=f"legacy_{direction}",
|
|
498
|
+
policy_context=policy_context,
|
|
499
|
+
sanitize=True,
|
|
500
|
+
)
|
|
501
|
+
return await original(secured, *args, **kwargs)
|
|
502
|
+
|
|
503
|
+
def sync_wrapper(_agent: Any, message: Any, *args: Any, **kwargs: Any) -> Any:
|
|
504
|
+
peer = args[0] if args else kwargs.get("recipient") or kwargs.get("sender")
|
|
505
|
+
peer_id = _agent_name(peer, "autogen_peer")
|
|
506
|
+
sender, recipient = (agent_id, peer_id) if direction == "send" else (peer_id, agent_id)
|
|
507
|
+
secured = self.inspect_message(
|
|
508
|
+
message,
|
|
509
|
+
session_id=session_id,
|
|
510
|
+
sender_agent_id=sender,
|
|
511
|
+
recipient_agent_id=recipient,
|
|
512
|
+
direction=f"legacy_{direction}",
|
|
513
|
+
policy_context=policy_context,
|
|
514
|
+
sanitize=True,
|
|
515
|
+
)
|
|
516
|
+
return original(secured, *args, **kwargs)
|
|
517
|
+
|
|
518
|
+
setattr(agent, method_name, MethodType(async_wrapper if is_async else sync_wrapper, agent))
|
|
519
|
+
return True
|
|
520
|
+
|
|
521
|
+
def attach_conversable_agent(
|
|
522
|
+
self,
|
|
523
|
+
agent: Any,
|
|
524
|
+
*,
|
|
525
|
+
session_id: Optional[str] = None,
|
|
526
|
+
agent_id: Optional[str] = None,
|
|
527
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
528
|
+
) -> Any:
|
|
529
|
+
"""Attach to legacy AutoGen 0.2 ConversableAgent send/receive lifecycles."""
|
|
530
|
+
sid = self.session_id(session_id, agent)
|
|
531
|
+
aid = agent_id or _agent_name(agent, self.config.agent_id)
|
|
532
|
+
for name, direction in (("send", "send"), ("receive", "receive"), ("a_send", "send"), ("a_receive", "receive")):
|
|
533
|
+
self._attach_method(
|
|
534
|
+
agent,
|
|
535
|
+
name,
|
|
536
|
+
session_id=sid,
|
|
537
|
+
agent_id=aid,
|
|
538
|
+
direction=direction,
|
|
539
|
+
policy_context=policy_context,
|
|
540
|
+
)
|
|
541
|
+
return agent
|
|
542
|
+
|
|
543
|
+
def attach_agentchat_agent(
|
|
544
|
+
self,
|
|
545
|
+
agent: Any,
|
|
546
|
+
*,
|
|
547
|
+
session_id: Optional[str] = None,
|
|
548
|
+
agent_id: Optional[str] = None,
|
|
549
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
550
|
+
) -> Any:
|
|
551
|
+
"""Attach to current AutoGen BaseChatAgent.on_messages/on_messages_stream."""
|
|
552
|
+
sid = self.session_id(session_id, agent)
|
|
553
|
+
aid = agent_id or _agent_name(agent, self.config.agent_id)
|
|
554
|
+
original = getattr(agent, "on_messages", None)
|
|
555
|
+
if callable(original) and not hasattr(agent, "_agenticdome_original_on_messages"):
|
|
556
|
+
setattr(agent, "_agenticdome_original_on_messages", original)
|
|
557
|
+
|
|
558
|
+
async def on_messages(_agent: Any, messages: Iterable[Any], *args: Any, **kwargs: Any) -> Any:
|
|
559
|
+
secured = []
|
|
560
|
+
for message in messages:
|
|
561
|
+
secured.append(
|
|
562
|
+
await self.ainspect_message(
|
|
563
|
+
message,
|
|
564
|
+
session_id=sid,
|
|
565
|
+
sender_agent_id=_agent_name(message, "autogen_peer"),
|
|
566
|
+
recipient_agent_id=aid,
|
|
567
|
+
direction="agentchat_receive",
|
|
568
|
+
policy_context=policy_context,
|
|
569
|
+
sanitize=True,
|
|
570
|
+
)
|
|
571
|
+
)
|
|
572
|
+
response = await original(secured, *args, **kwargs)
|
|
573
|
+
chat_message = getattr(response, "chat_message", None)
|
|
574
|
+
if chat_message is not None:
|
|
575
|
+
reviewed = await self.ainspect_message(
|
|
576
|
+
chat_message,
|
|
577
|
+
session_id=sid,
|
|
578
|
+
sender_agent_id=aid,
|
|
579
|
+
recipient_agent_id="autogen_team",
|
|
580
|
+
direction="agentchat_send",
|
|
581
|
+
policy_context=policy_context,
|
|
582
|
+
sanitize=True,
|
|
583
|
+
)
|
|
584
|
+
try:
|
|
585
|
+
updated = copy.copy(response)
|
|
586
|
+
updated.chat_message = reviewed
|
|
587
|
+
return updated
|
|
588
|
+
except Exception:
|
|
589
|
+
pass
|
|
590
|
+
return response
|
|
591
|
+
|
|
592
|
+
setattr(agent, "on_messages", MethodType(on_messages, agent))
|
|
593
|
+
return agent
|
|
594
|
+
|
|
595
|
+
def create_intervention_handler(
|
|
596
|
+
self,
|
|
597
|
+
*,
|
|
598
|
+
session_id: Optional[str] = None,
|
|
599
|
+
agent_id: Optional[str] = None,
|
|
600
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
601
|
+
) -> Any:
|
|
602
|
+
"""Create an AutoGen Core intervention handler for messages and FunctionCall tools."""
|
|
603
|
+
try:
|
|
604
|
+
from autogen_core import DefaultInterventionHandler, DropMessage, FunctionCall
|
|
605
|
+
except ImportError as exc:
|
|
606
|
+
raise ImportError(
|
|
607
|
+
"AutoGen integration requires Python 3.10+ and: pip install 'agenticdome-python-sdk[autogen]'"
|
|
608
|
+
) from exc
|
|
609
|
+
|
|
610
|
+
firewall = self
|
|
611
|
+
sid = self.session_id(session_id)
|
|
612
|
+
aid = agent_id or self.config.agent_id
|
|
613
|
+
|
|
614
|
+
class AgenticDomeInterventionHandler(DefaultInterventionHandler):
|
|
615
|
+
async def on_send(self, message: Any, *, message_context: Any, recipient: Any) -> Any:
|
|
616
|
+
sender = _agent_name(getattr(message_context, "sender", None), aid)
|
|
617
|
+
recipient_id = _agent_name(recipient, "autogen_recipient")
|
|
618
|
+
try:
|
|
619
|
+
if isinstance(message, FunctionCall):
|
|
620
|
+
args = firewall.normalize_args(getattr(message, "arguments", {}))
|
|
621
|
+
# Keep Core message ordering deterministic. The SDK client is
|
|
622
|
+
# synchronous, and dispatching this boundary to the loop's
|
|
623
|
+
# default executor can outlive short-lived AutoGen runtimes.
|
|
624
|
+
decision = firewall.authorize_tool_call(
|
|
625
|
+
session_id=sid,
|
|
626
|
+
agent_id=sender,
|
|
627
|
+
source_agent_id=sender,
|
|
628
|
+
tool_name=str(getattr(message, "name", "autogen.tool")),
|
|
629
|
+
tool_args=args,
|
|
630
|
+
tool_platform="autogen_core",
|
|
631
|
+
text=f"[Microsoft AutoGen] {sender} requests a tool execution",
|
|
632
|
+
policy_context={**dict(policy_context or {}), "recipient_agent_id": recipient_id},
|
|
633
|
+
)
|
|
634
|
+
clean = firewall.sanitized_args(decision, args)
|
|
635
|
+
if clean != args:
|
|
636
|
+
try:
|
|
637
|
+
return message.model_copy(update={"arguments": json.dumps(clean)})
|
|
638
|
+
except Exception:
|
|
639
|
+
pass
|
|
640
|
+
return await firewall.ainspect_message(
|
|
641
|
+
message,
|
|
642
|
+
session_id=sid,
|
|
643
|
+
sender_agent_id=sender,
|
|
644
|
+
recipient_agent_id=recipient_id,
|
|
645
|
+
direction="core_send",
|
|
646
|
+
policy_context=policy_context,
|
|
647
|
+
sanitize=True,
|
|
648
|
+
)
|
|
649
|
+
except AutoGenFirewallDenied:
|
|
650
|
+
return DropMessage
|
|
651
|
+
|
|
652
|
+
return AgenticDomeInterventionHandler()
|
|
653
|
+
|
|
654
|
+
def create_termination_condition(
|
|
655
|
+
self,
|
|
656
|
+
*,
|
|
657
|
+
session_id: Optional[str] = None,
|
|
658
|
+
agent_id: Optional[str] = None,
|
|
659
|
+
policy_context: Optional[Dict[str, Any]] = None,
|
|
660
|
+
) -> Any:
|
|
661
|
+
"""Create a composable AgentChat termination condition that freezes on policy denial."""
|
|
662
|
+
try:
|
|
663
|
+
from autogen_agentchat.base import TerminationCondition
|
|
664
|
+
from autogen_agentchat.messages import StopMessage
|
|
665
|
+
except ImportError as exc:
|
|
666
|
+
raise ImportError(
|
|
667
|
+
"AutoGen integration requires Python 3.10+ and: pip install 'agenticdome-python-sdk[autogen]'"
|
|
668
|
+
) from exc
|
|
669
|
+
|
|
670
|
+
firewall = self
|
|
671
|
+
sid = self.session_id(session_id)
|
|
672
|
+
aid = agent_id or self.config.agent_id
|
|
673
|
+
|
|
674
|
+
class AgenticDomeTermination(TerminationCondition):
|
|
675
|
+
@property
|
|
676
|
+
def terminated(self) -> bool:
|
|
677
|
+
return firewall.is_session_frozen(sid)
|
|
678
|
+
|
|
679
|
+
async def __call__(self, messages: Iterable[Any]) -> Optional[Any]:
|
|
680
|
+
try:
|
|
681
|
+
for message in messages:
|
|
682
|
+
await firewall.ainspect_message(
|
|
683
|
+
message,
|
|
684
|
+
session_id=sid,
|
|
685
|
+
sender_agent_id=_agent_name(message, aid),
|
|
686
|
+
recipient_agent_id="autogen_team",
|
|
687
|
+
direction="termination_check",
|
|
688
|
+
policy_context=policy_context,
|
|
689
|
+
sanitize=False,
|
|
690
|
+
)
|
|
691
|
+
except AutoGenFirewallDenied as exc:
|
|
692
|
+
return StopMessage(content=str(exc), source="AgenticDome")
|
|
693
|
+
return None
|
|
694
|
+
|
|
695
|
+
async def reset(self) -> None:
|
|
696
|
+
firewall.unfreeze_session(sid)
|
|
697
|
+
|
|
698
|
+
return AgenticDomeTermination()
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
__all__ = [
|
|
702
|
+
"AgenticDomeAutoGenFirewall",
|
|
703
|
+
"AutoGenFirewallConfigurationError",
|
|
704
|
+
"AutoGenFirewallDenied",
|
|
705
|
+
"AutoGenFirewallError",
|
|
706
|
+
"FirewallConfig",
|
|
707
|
+
"SecureAutoGenTeam",
|
|
708
|
+
"load_config",
|
|
709
|
+
]
|
|
File without changes
|
{agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{agenticdome_python_sdk-1.2.2.dist-info → agenticdome_python_sdk-1.2.3.dist-info}/top_level.txt
RENAMED
|
File without changes
|