agent_os_kernel 3.1.0__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.
Files changed (337) hide show
  1. agent_control_plane/__init__.py +662 -0
  2. agent_control_plane/a2a_adapter.py +543 -0
  3. agent_control_plane/adapter.py +417 -0
  4. agent_control_plane/agent_hibernation.py +394 -0
  5. agent_control_plane/agent_kernel.py +470 -0
  6. agent_control_plane/compliance.py +720 -0
  7. agent_control_plane/constraint_graphs.py +478 -0
  8. agent_control_plane/control_plane.py +854 -0
  9. agent_control_plane/example_executors.py +195 -0
  10. agent_control_plane/execution_engine.py +231 -0
  11. agent_control_plane/flight_recorder.py +846 -0
  12. agent_control_plane/governance_layer.py +435 -0
  13. agent_control_plane/hf_utils.py +563 -0
  14. agent_control_plane/interfaces/__init__.py +55 -0
  15. agent_control_plane/interfaces/kernel_interface.py +361 -0
  16. agent_control_plane/interfaces/plugin_interface.py +497 -0
  17. agent_control_plane/interfaces/protocol_interfaces.py +387 -0
  18. agent_control_plane/kernel_space.py +1009 -0
  19. agent_control_plane/langchain_adapter.py +424 -0
  20. agent_control_plane/lifecycle.py +3113 -0
  21. agent_control_plane/mcp_adapter.py +653 -0
  22. agent_control_plane/ml_safety.py +563 -0
  23. agent_control_plane/multimodal.py +727 -0
  24. agent_control_plane/mute_agent.py +422 -0
  25. agent_control_plane/observability.py +787 -0
  26. agent_control_plane/orchestrator.py +482 -0
  27. agent_control_plane/plugin_registry.py +750 -0
  28. agent_control_plane/policy_engine.py +954 -0
  29. agent_control_plane/process_isolation.py +777 -0
  30. agent_control_plane/shadow_mode.py +310 -0
  31. agent_control_plane/signals.py +493 -0
  32. agent_control_plane/supervisor_agents.py +430 -0
  33. agent_control_plane/time_travel_debugger.py +557 -0
  34. agent_control_plane/tool_registry.py +452 -0
  35. agent_control_plane/vfs.py +697 -0
  36. agent_kernel/__init__.py +69 -0
  37. agent_kernel/analyzer.py +435 -0
  38. agent_kernel/auditor.py +36 -0
  39. agent_kernel/completeness_auditor.py +237 -0
  40. agent_kernel/detector.py +203 -0
  41. agent_kernel/kernel.py +744 -0
  42. agent_kernel/memory_manager.py +85 -0
  43. agent_kernel/models.py +374 -0
  44. agent_kernel/nudge_mechanism.py +263 -0
  45. agent_kernel/outcome_analyzer.py +338 -0
  46. agent_kernel/patcher.py +582 -0
  47. agent_kernel/semantic_analyzer.py +316 -0
  48. agent_kernel/semantic_purge.py +349 -0
  49. agent_kernel/simulator.py +449 -0
  50. agent_kernel/teacher.py +85 -0
  51. agent_kernel/triage.py +152 -0
  52. agent_os/__init__.py +409 -0
  53. agent_os/_adversarial_impl.py +200 -0
  54. agent_os/_circuit_breaker_impl.py +232 -0
  55. agent_os/_mcp_metrics.py +193 -0
  56. agent_os/adversarial.py +20 -0
  57. agent_os/agents_compat.py +490 -0
  58. agent_os/audit_logger.py +135 -0
  59. agent_os/base_agent.py +651 -0
  60. agent_os/circuit_breaker.py +34 -0
  61. agent_os/cli/__init__.py +659 -0
  62. agent_os/cli/cmd_audit.py +128 -0
  63. agent_os/cli/cmd_init.py +152 -0
  64. agent_os/cli/cmd_policy.py +41 -0
  65. agent_os/cli/cmd_policy_gen.py +180 -0
  66. agent_os/cli/cmd_validate.py +258 -0
  67. agent_os/cli/mcp_scan.py +265 -0
  68. agent_os/cli/output.py +192 -0
  69. agent_os/cli/policy_checker.py +330 -0
  70. agent_os/compat.py +74 -0
  71. agent_os/constraint_graph.py +234 -0
  72. agent_os/content_governance.py +140 -0
  73. agent_os/context_budget.py +305 -0
  74. agent_os/credential_redactor.py +224 -0
  75. agent_os/diff_policy.py +89 -0
  76. agent_os/egress_policy.py +159 -0
  77. agent_os/escalation.py +276 -0
  78. agent_os/event_bus.py +124 -0
  79. agent_os/exceptions.py +180 -0
  80. agent_os/execution_context_policy.py +141 -0
  81. agent_os/github_enterprise.py +96 -0
  82. agent_os/health.py +20 -0
  83. agent_os/integrations/__init__.py +279 -0
  84. agent_os/integrations/a2a_adapter.py +279 -0
  85. agent_os/integrations/agent_lightning/__init__.py +30 -0
  86. agent_os/integrations/anthropic_adapter.py +420 -0
  87. agent_os/integrations/autogen_adapter.py +620 -0
  88. agent_os/integrations/base.py +1137 -0
  89. agent_os/integrations/compat.py +229 -0
  90. agent_os/integrations/config.py +98 -0
  91. agent_os/integrations/conversation_guardian.py +957 -0
  92. agent_os/integrations/crewai_adapter.py +467 -0
  93. agent_os/integrations/drift_detector.py +425 -0
  94. agent_os/integrations/dry_run.py +124 -0
  95. agent_os/integrations/escalation.py +582 -0
  96. agent_os/integrations/gemini_adapter.py +364 -0
  97. agent_os/integrations/google_adk_adapter.py +633 -0
  98. agent_os/integrations/guardrails_adapter.py +394 -0
  99. agent_os/integrations/health.py +197 -0
  100. agent_os/integrations/langchain_adapter.py +654 -0
  101. agent_os/integrations/llamafirewall.py +343 -0
  102. agent_os/integrations/llamaindex_adapter.py +188 -0
  103. agent_os/integrations/logging.py +191 -0
  104. agent_os/integrations/maf_adapter.py +631 -0
  105. agent_os/integrations/mistral_adapter.py +365 -0
  106. agent_os/integrations/openai_adapter.py +816 -0
  107. agent_os/integrations/openai_agents_sdk.py +406 -0
  108. agent_os/integrations/policy_compose.py +171 -0
  109. agent_os/integrations/profiling.py +144 -0
  110. agent_os/integrations/pydantic_ai_adapter.py +420 -0
  111. agent_os/integrations/rate_limiter.py +130 -0
  112. agent_os/integrations/rbac.py +143 -0
  113. agent_os/integrations/registry.py +113 -0
  114. agent_os/integrations/scope_guard.py +303 -0
  115. agent_os/integrations/semantic_kernel_adapter.py +769 -0
  116. agent_os/integrations/smolagents_adapter.py +629 -0
  117. agent_os/integrations/templates.py +178 -0
  118. agent_os/integrations/token_budget.py +134 -0
  119. agent_os/integrations/tool_aliases.py +190 -0
  120. agent_os/integrations/webhooks.py +177 -0
  121. agent_os/lite.py +208 -0
  122. agent_os/mcp_gateway.py +385 -0
  123. agent_os/mcp_message_signer.py +273 -0
  124. agent_os/mcp_protocols.py +161 -0
  125. agent_os/mcp_response_scanner.py +232 -0
  126. agent_os/mcp_security.py +924 -0
  127. agent_os/mcp_session_auth.py +231 -0
  128. agent_os/mcp_sliding_rate_limiter.py +184 -0
  129. agent_os/memory_guard.py +409 -0
  130. agent_os/metrics.py +134 -0
  131. agent_os/mute.py +428 -0
  132. agent_os/mute_agent.py +209 -0
  133. agent_os/policies/__init__.py +77 -0
  134. agent_os/policies/async_evaluator.py +275 -0
  135. agent_os/policies/backends.py +670 -0
  136. agent_os/policies/bridge.py +169 -0
  137. agent_os/policies/budget.py +85 -0
  138. agent_os/policies/cli.py +294 -0
  139. agent_os/policies/conflict_resolution.py +270 -0
  140. agent_os/policies/data_classification.py +252 -0
  141. agent_os/policies/evaluator.py +239 -0
  142. agent_os/policies/policy_schema.json +228 -0
  143. agent_os/policies/rate_limiting.py +145 -0
  144. agent_os/policies/schema.py +115 -0
  145. agent_os/policies/shared.py +331 -0
  146. agent_os/prompt_injection.py +694 -0
  147. agent_os/providers.py +182 -0
  148. agent_os/py.typed +0 -0
  149. agent_os/retry.py +81 -0
  150. agent_os/reversibility.py +251 -0
  151. agent_os/sandbox.py +432 -0
  152. agent_os/sandbox_provider.py +140 -0
  153. agent_os/secure_codegen.py +525 -0
  154. agent_os/security_skills.py +538 -0
  155. agent_os/semantic_policy.py +422 -0
  156. agent_os/server/__init__.py +15 -0
  157. agent_os/server/__main__.py +25 -0
  158. agent_os/server/app.py +277 -0
  159. agent_os/server/models.py +104 -0
  160. agent_os/shift_left_metrics.py +130 -0
  161. agent_os/stateless.py +742 -0
  162. agent_os/supervisor.py +148 -0
  163. agent_os/task_outcome.py +148 -0
  164. agent_os/transparency.py +181 -0
  165. agent_os/trust_root.py +128 -0
  166. agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
  167. agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
  168. agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
  169. agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
  170. agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
  171. agent_os_observability/__init__.py +27 -0
  172. agent_os_observability/dashboards.py +898 -0
  173. agent_os_observability/metrics.py +398 -0
  174. agent_os_observability/server.py +223 -0
  175. agent_os_observability/tracer.py +232 -0
  176. agent_primitives/__init__.py +24 -0
  177. agent_primitives/failures.py +84 -0
  178. agent_primitives/py.typed +0 -0
  179. amb_core/__init__.py +177 -0
  180. amb_core/adapters/__init__.py +57 -0
  181. amb_core/adapters/aws_sqs_broker.py +376 -0
  182. amb_core/adapters/azure_servicebus_broker.py +340 -0
  183. amb_core/adapters/kafka_broker.py +260 -0
  184. amb_core/adapters/nats_broker.py +285 -0
  185. amb_core/adapters/rabbitmq_broker.py +235 -0
  186. amb_core/adapters/redis_broker.py +262 -0
  187. amb_core/broker.py +145 -0
  188. amb_core/bus.py +481 -0
  189. amb_core/cloudevents.py +509 -0
  190. amb_core/dlq.py +345 -0
  191. amb_core/hf_utils.py +536 -0
  192. amb_core/memory_broker.py +410 -0
  193. amb_core/models.py +141 -0
  194. amb_core/persistence.py +529 -0
  195. amb_core/schema.py +294 -0
  196. amb_core/tracing.py +358 -0
  197. atr/__init__.py +640 -0
  198. atr/access.py +348 -0
  199. atr/composition.py +645 -0
  200. atr/decorator.py +357 -0
  201. atr/executor.py +384 -0
  202. atr/health.py +557 -0
  203. atr/hf_utils.py +449 -0
  204. atr/injection.py +422 -0
  205. atr/metrics.py +440 -0
  206. atr/policies.py +403 -0
  207. atr/py.typed +2 -0
  208. atr/registry.py +452 -0
  209. atr/schema.py +480 -0
  210. atr/tools/safe/__init__.py +75 -0
  211. atr/tools/safe/calculator.py +467 -0
  212. atr/tools/safe/datetime_tool.py +443 -0
  213. atr/tools/safe/file_reader.py +402 -0
  214. atr/tools/safe/http_client.py +316 -0
  215. atr/tools/safe/json_parser.py +374 -0
  216. atr/tools/safe/text_tool.py +537 -0
  217. atr/tools/safe/toolkit.py +175 -0
  218. caas/__init__.py +162 -0
  219. caas/api/__init__.py +7 -0
  220. caas/api/server.py +1328 -0
  221. caas/caching.py +834 -0
  222. caas/cli.py +210 -0
  223. caas/conversation.py +223 -0
  224. caas/decay.py +72 -0
  225. caas/detection/__init__.py +9 -0
  226. caas/detection/detector.py +238 -0
  227. caas/enrichment.py +130 -0
  228. caas/gateway/__init__.py +27 -0
  229. caas/gateway/trust_gateway.py +474 -0
  230. caas/hf_utils.py +479 -0
  231. caas/ingestion/__init__.py +23 -0
  232. caas/ingestion/processors.py +253 -0
  233. caas/ingestion/structure_parser.py +188 -0
  234. caas/models.py +356 -0
  235. caas/pragmatic_truth.py +444 -0
  236. caas/routing/__init__.py +10 -0
  237. caas/routing/heuristic_router.py +58 -0
  238. caas/storage/__init__.py +9 -0
  239. caas/storage/store.py +389 -0
  240. caas/triad.py +213 -0
  241. caas/tuning/__init__.py +9 -0
  242. caas/tuning/tuner.py +329 -0
  243. caas/vfs/__init__.py +14 -0
  244. caas/vfs/filesystem.py +452 -0
  245. cmvk/__init__.py +218 -0
  246. cmvk/audit.py +402 -0
  247. cmvk/benchmarks.py +478 -0
  248. cmvk/constitutional.py +904 -0
  249. cmvk/hf_utils.py +301 -0
  250. cmvk/metrics.py +473 -0
  251. cmvk/profiles.py +300 -0
  252. cmvk/py.typed +0 -0
  253. cmvk/types.py +12 -0
  254. cmvk/verification.py +956 -0
  255. emk/__init__.py +89 -0
  256. emk/causal.py +352 -0
  257. emk/hf_utils.py +421 -0
  258. emk/indexer.py +83 -0
  259. emk/py.typed +0 -0
  260. emk/schema.py +204 -0
  261. emk/sleep_cycle.py +347 -0
  262. emk/store.py +281 -0
  263. iatp/__init__.py +166 -0
  264. iatp/attestation.py +461 -0
  265. iatp/cli.py +317 -0
  266. iatp/hf_utils.py +472 -0
  267. iatp/ipc_pipes.py +580 -0
  268. iatp/main.py +412 -0
  269. iatp/models/__init__.py +447 -0
  270. iatp/policy_engine.py +337 -0
  271. iatp/py.typed +2 -0
  272. iatp/recovery.py +321 -0
  273. iatp/security/__init__.py +270 -0
  274. iatp/sidecar/__init__.py +519 -0
  275. iatp/telemetry/__init__.py +164 -0
  276. iatp/tests/__init__.py +1 -0
  277. iatp/tests/test_attestation.py +370 -0
  278. iatp/tests/test_cli.py +131 -0
  279. iatp/tests/test_ed25519_attestation.py +211 -0
  280. iatp/tests/test_models.py +130 -0
  281. iatp/tests/test_policy_engine.py +347 -0
  282. iatp/tests/test_recovery.py +281 -0
  283. iatp/tests/test_security.py +222 -0
  284. iatp/tests/test_sidecar.py +167 -0
  285. iatp/tests/test_telemetry.py +175 -0
  286. mcp_kernel_server/__init__.py +28 -0
  287. mcp_kernel_server/cli.py +274 -0
  288. mcp_kernel_server/resources.py +217 -0
  289. mcp_kernel_server/server.py +564 -0
  290. mcp_kernel_server/tools.py +1174 -0
  291. mute_agent/__init__.py +68 -0
  292. mute_agent/core/__init__.py +1 -0
  293. mute_agent/core/execution_agent.py +166 -0
  294. mute_agent/core/handshake_protocol.py +201 -0
  295. mute_agent/core/reasoning_agent.py +238 -0
  296. mute_agent/knowledge_graph/__init__.py +1 -0
  297. mute_agent/knowledge_graph/graph_elements.py +65 -0
  298. mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
  299. mute_agent/knowledge_graph/subgraph.py +224 -0
  300. mute_agent/listener/__init__.py +43 -0
  301. mute_agent/listener/adapters/__init__.py +31 -0
  302. mute_agent/listener/adapters/base_adapter.py +189 -0
  303. mute_agent/listener/adapters/caas_adapter.py +344 -0
  304. mute_agent/listener/adapters/control_plane_adapter.py +436 -0
  305. mute_agent/listener/adapters/iatp_adapter.py +332 -0
  306. mute_agent/listener/adapters/scak_adapter.py +251 -0
  307. mute_agent/listener/listener.py +610 -0
  308. mute_agent/listener/state_observer.py +436 -0
  309. mute_agent/listener/threshold_config.py +313 -0
  310. mute_agent/super_system/__init__.py +1 -0
  311. mute_agent/super_system/router.py +204 -0
  312. mute_agent/visualization/__init__.py +10 -0
  313. mute_agent/visualization/graph_debugger.py +502 -0
  314. nexus/README.md +60 -0
  315. nexus/__init__.py +51 -0
  316. nexus/arbiter.py +359 -0
  317. nexus/client.py +466 -0
  318. nexus/dmz.py +444 -0
  319. nexus/escrow.py +430 -0
  320. nexus/exceptions.py +286 -0
  321. nexus/pyproject.toml +36 -0
  322. nexus/registry.py +393 -0
  323. nexus/reputation.py +425 -0
  324. nexus/schemas/__init__.py +51 -0
  325. nexus/schemas/compliance.py +276 -0
  326. nexus/schemas/escrow.py +251 -0
  327. nexus/schemas/manifest.py +225 -0
  328. nexus/schemas/receipt.py +208 -0
  329. nexus/tests/__init__.py +0 -0
  330. nexus/tests/conftest.py +146 -0
  331. nexus/tests/test_arbiter.py +192 -0
  332. nexus/tests/test_dmz.py +194 -0
  333. nexus/tests/test_escrow.py +276 -0
  334. nexus/tests/test_exceptions.py +225 -0
  335. nexus/tests/test_registry.py +232 -0
  336. nexus/tests/test_reputation.py +328 -0
  337. nexus/tests/test_schemas.py +295 -0
@@ -0,0 +1,406 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ OpenAI Agents SDK Integration for Agent-OS
5
+ ============================================
6
+
7
+ Provides kernel-level governance for OpenAI Agents SDK workflows.
8
+
9
+ Features:
10
+ - Policy enforcement for agent tool calls
11
+ - Guardrails integration with Agent-OS policies
12
+ - Handoff monitoring and approval
13
+ - Streaming response governance
14
+
15
+ Example:
16
+ >>> from agent_os.integrations.openai_agents import OpenAIAgentsKernel
17
+ >>> from agent_os.policies import GovernancePolicy
18
+ >>> from agents import Agent, Runner
19
+ >>>
20
+ >>> # Create governed kernel
21
+ >>> policy = GovernancePolicy(
22
+ ... max_tool_calls=10,
23
+ ... allowed_tools=["file_search", "code_interpreter"],
24
+ ... blocked_patterns=["rm -rf", "DROP TABLE"],
25
+ ... )
26
+ >>> kernel = OpenAIAgentsKernel(policy=policy)
27
+ >>>
28
+ >>> # Wrap agent
29
+ >>> agent = Agent(name="assistant", model="gpt-4o")
30
+ >>> governed_agent = kernel.wrap(agent)
31
+ >>>
32
+ >>> # Run with governance
33
+ >>> result = await Runner.run(governed_agent, "Analyze this data")
34
+ """
35
+
36
+ from __future__ import annotations
37
+
38
+ import asyncio
39
+ import logging
40
+ import time
41
+ from dataclasses import dataclass, field
42
+ from datetime import datetime, timezone
43
+ from functools import wraps
44
+ from typing import Any, Callable
45
+
46
+ logger = logging.getLogger(__name__)
47
+
48
+
49
+ @dataclass
50
+ class GovernancePolicy:
51
+ """Policy configuration for OpenAI Agents."""
52
+ # Tool limits
53
+ max_tool_calls: int = 50
54
+ max_handoffs: int = 5
55
+ timeout_seconds: int = 300
56
+
57
+ # Tool filtering
58
+ allowed_tools: list[str] = field(default_factory=list)
59
+ blocked_tools: list[str] = field(default_factory=list)
60
+
61
+ # Content filtering
62
+ blocked_patterns: list[str] = field(default_factory=list)
63
+ pii_detection: bool = True
64
+
65
+ # Approval flows
66
+ require_human_approval: bool = False
67
+ approval_threshold: float = 0.8
68
+
69
+ # Audit
70
+ log_all_calls: bool = True
71
+ checkpoint_frequency: int = 5
72
+
73
+
74
+ @dataclass
75
+ class ExecutionContext:
76
+ """Runtime context for governed execution."""
77
+ session_id: str
78
+ agent_id: str
79
+ policy: GovernancePolicy
80
+
81
+ # Counters
82
+ tool_calls: int = 0
83
+ handoffs: int = 0
84
+
85
+ # Timing
86
+ started_at: datetime = field(default_factory=datetime.utcnow)
87
+
88
+ # Audit trail
89
+ events: list[dict[str, Any]] = field(default_factory=list)
90
+
91
+ def record_event(self, event_type: str, data: dict[str, Any]) -> None:
92
+ self.events.append({
93
+ "type": event_type,
94
+ "timestamp": datetime.now(timezone.utc).isoformat(),
95
+ "data": data,
96
+ })
97
+
98
+
99
+ class PolicyViolationError(Exception):
100
+ """Raised when a policy violation is detected."""
101
+ def __init__(self, policy_name: str, description: str, severity: str = "high"):
102
+ self.policy_name = policy_name
103
+ self.description = description
104
+ self.severity = severity
105
+ super().__init__(f"Policy violation ({policy_name}): {description}")
106
+
107
+
108
+ class OpenAIAgentsKernel:
109
+ """
110
+ Governance kernel for OpenAI Agents SDK.
111
+
112
+ Wraps Agent and Runner to enforce policies during execution.
113
+ """
114
+
115
+ def __init__(
116
+ self,
117
+ policy: GovernancePolicy | None = None,
118
+ on_violation: Callable[[PolicyViolationError], None] | None = None,
119
+ ) -> None:
120
+ self.policy: GovernancePolicy = policy or GovernancePolicy()
121
+ self.on_violation: Callable[[PolicyViolationError], None] = (
122
+ on_violation or self._default_violation_handler
123
+ )
124
+ self._contexts: dict[str, ExecutionContext] = {}
125
+ self._wrapped_agents: dict[str, Any] = {}
126
+ self._start_time: float = time.monotonic()
127
+ self._last_error: str | None = None
128
+
129
+ def _default_violation_handler(self, error: PolicyViolationError) -> None:
130
+ logger.error(f"Policy violation: {error}")
131
+
132
+ def _create_context(self, agent_id: str) -> ExecutionContext:
133
+ """Create execution context for an agent."""
134
+ import uuid
135
+ session_id = str(uuid.uuid4())[:8]
136
+ ctx = ExecutionContext(
137
+ session_id=session_id,
138
+ agent_id=agent_id,
139
+ policy=self.policy,
140
+ )
141
+ self._contexts[session_id] = ctx
142
+ return ctx
143
+
144
+ def _check_tool_allowed(self, tool_name: str) -> tuple[bool, str]:
145
+ """Check if tool is allowed by policy."""
146
+ # Check blocked list
147
+ if tool_name in self.policy.blocked_tools:
148
+ return False, f"Tool '{tool_name}' is blocked by policy"
149
+
150
+ # Check allowed list (if specified)
151
+ if self.policy.allowed_tools:
152
+ if tool_name not in self.policy.allowed_tools:
153
+ return False, f"Tool '{tool_name}' not in allowed list"
154
+
155
+ return True, ""
156
+
157
+ def _check_content(self, content: str) -> tuple[bool, str]:
158
+ """Check content against blocked patterns."""
159
+ content_lower = content.lower()
160
+ for pattern in self.policy.blocked_patterns:
161
+ if pattern.lower() in content_lower:
162
+ return False, f"Content matches blocked pattern: {pattern}"
163
+ return True, ""
164
+
165
+ def wrap(self, agent: Any) -> Any:
166
+ """
167
+ Wrap an OpenAI Agent with governance.
168
+
169
+ Args:
170
+ agent: OpenAI Agents SDK Agent instance
171
+
172
+ Returns:
173
+ Governed agent wrapper
174
+ """
175
+ agent_id = getattr(agent, "name", str(id(agent)))
176
+
177
+ # Create wrapper class
178
+ class GovernedAgent:
179
+ def __init__(wrapper_self, original: Any, kernel: OpenAIAgentsKernel):
180
+ wrapper_self._original = original
181
+ wrapper_self._kernel = kernel
182
+ wrapper_self._context = kernel._create_context(agent_id)
183
+
184
+ # Copy attributes
185
+ for attr in ["name", "model", "instructions", "tools"]:
186
+ if hasattr(original, attr):
187
+ setattr(wrapper_self, attr, getattr(original, attr))
188
+
189
+ @property
190
+ def original(wrapper_self) -> Any:
191
+ return wrapper_self._original
192
+
193
+ def __getattr__(wrapper_self, name: str) -> Any:
194
+ return getattr(wrapper_self._original, name)
195
+
196
+ wrapped = GovernedAgent(agent, self)
197
+ self._wrapped_agents[agent_id] = wrapped
198
+ logger.info(f"Wrapped agent '{agent_id}' with governance kernel")
199
+ return wrapped
200
+
201
+ def unwrap(self, governed_agent: Any) -> Any:
202
+ """Remove governance wrapper."""
203
+ if hasattr(governed_agent, "_original"):
204
+ return governed_agent._original
205
+ return governed_agent
206
+
207
+ def wrap_runner(self, runner_class: Any) -> Any:
208
+ """
209
+ Wrap the Runner class to intercept executions.
210
+
211
+ Args:
212
+ runner_class: OpenAI Agents SDK Runner class
213
+
214
+ Returns:
215
+ Governed Runner class
216
+ """
217
+ kernel = self
218
+
219
+ class GovernedRunner:
220
+ @classmethod
221
+ async def run(
222
+ cls,
223
+ agent: Any,
224
+ input_text: str,
225
+ **kwargs,
226
+ ) -> Any:
227
+ # Get context
228
+ ctx = None
229
+ if hasattr(agent, "_context"):
230
+ ctx = agent._context
231
+
232
+ # Pre-execution checks
233
+ if ctx:
234
+ # Check content
235
+ ok, reason = kernel._check_content(input_text)
236
+ if not ok:
237
+ error = PolicyViolationError("content_filter", reason)
238
+ kernel.on_violation(error)
239
+ if kernel.policy.require_human_approval:
240
+ raise error
241
+
242
+ ctx.record_event("run_start", {"input_length": len(input_text)})
243
+
244
+ # Get original agent
245
+ original_agent = agent
246
+ if hasattr(agent, "_original"):
247
+ original_agent = agent._original
248
+
249
+ # Run with monitoring
250
+ try:
251
+ result = await runner_class.run(original_agent, input_text, **kwargs)
252
+
253
+ if ctx:
254
+ ctx.record_event("run_complete", {"success": True})
255
+
256
+ return result
257
+ except Exception as e:
258
+ if ctx:
259
+ ctx.record_event("run_error", {"error": str(e)})
260
+ raise
261
+
262
+ @classmethod
263
+ def run_sync(cls, agent: Any, input_text: str, **kwargs) -> Any:
264
+ return asyncio.run(cls.run(agent, input_text, **kwargs))
265
+
266
+ return GovernedRunner
267
+
268
+ def create_tool_guard(self) -> Callable:
269
+ """
270
+ Create a tool execution guard.
271
+
272
+ Use as a decorator or wrapper for tool functions.
273
+ """
274
+ kernel = self
275
+
276
+ def guard(func: Callable) -> Callable:
277
+ @wraps(func)
278
+ async def wrapper(*args, **kwargs):
279
+ tool_name = func.__name__
280
+
281
+ # Check if tool is allowed
282
+ ok, reason = kernel._check_tool_allowed(tool_name)
283
+ if not ok:
284
+ error = PolicyViolationError("tool_filter", reason)
285
+ kernel.on_violation(error)
286
+ raise error
287
+
288
+ # Check content in arguments
289
+ for arg in args:
290
+ if isinstance(arg, str):
291
+ ok, reason = kernel._check_content(arg)
292
+ if not ok:
293
+ error = PolicyViolationError("content_filter", reason)
294
+ kernel.on_violation(error)
295
+ raise error
296
+
297
+ for value in kwargs.values():
298
+ if isinstance(value, str):
299
+ ok, reason = kernel._check_content(value)
300
+ if not ok:
301
+ error = PolicyViolationError("content_filter", reason)
302
+ kernel.on_violation(error)
303
+ raise error
304
+
305
+ # Execute
306
+ if asyncio.iscoroutinefunction(func):
307
+ return await func(*args, **kwargs)
308
+ return func(*args, **kwargs)
309
+
310
+ return wrapper
311
+ return guard
312
+
313
+ def create_guardrail(self) -> Any:
314
+ """
315
+ Create an OpenAI Agents SDK compatible guardrail.
316
+
317
+ Returns a guardrail that can be added to an agent.
318
+ """
319
+ kernel = self
320
+
321
+ class PolicyGuardrail:
322
+ """Agent-OS policy guardrail for OpenAI Agents SDK."""
323
+
324
+ async def __call__(
325
+ self,
326
+ context: Any,
327
+ agent: Any,
328
+ input_text: str,
329
+ ) -> str | None:
330
+ """
331
+ Check input against policies.
332
+
333
+ Returns None if allowed, or a rejection message if blocked.
334
+ """
335
+ # Check content patterns
336
+ ok, reason = kernel._check_content(input_text)
337
+ if not ok:
338
+ logger.warning(f"Guardrail blocked: {reason}")
339
+ return f"Request blocked by policy: {reason}"
340
+
341
+ # Check tool calls if in context
342
+ if hasattr(context, "tool_calls"):
343
+ for tool_call in context.tool_calls:
344
+ tool_name = getattr(tool_call, "name", "")
345
+ ok, reason = kernel._check_tool_allowed(tool_name)
346
+ if not ok:
347
+ logger.warning(f"Guardrail blocked tool: {reason}")
348
+ return f"Tool blocked by policy: {reason}"
349
+
350
+ return None # Allowed
351
+
352
+ return PolicyGuardrail()
353
+
354
+ def get_context(self, session_id: str) -> ExecutionContext | None:
355
+ """Get execution context by session ID."""
356
+ return self._contexts.get(session_id)
357
+
358
+ def get_audit_log(self, session_id: str) -> list[dict[str, Any]]:
359
+ """Get audit log for a session."""
360
+ ctx = self._contexts.get(session_id)
361
+ if ctx:
362
+ return ctx.events
363
+ return []
364
+
365
+ def get_stats(self) -> dict[str, Any]:
366
+ """Get governance statistics."""
367
+ total_tool_calls: int = sum(ctx.tool_calls for ctx in self._contexts.values())
368
+ total_handoffs: int = sum(ctx.handoffs for ctx in self._contexts.values())
369
+
370
+ return {
371
+ "total_sessions": len(self._contexts),
372
+ "wrapped_agents": len(self._wrapped_agents),
373
+ "total_tool_calls": total_tool_calls,
374
+ "total_handoffs": total_handoffs,
375
+ "policy": {
376
+ "max_tool_calls": self.policy.max_tool_calls,
377
+ "max_handoffs": self.policy.max_handoffs,
378
+ "blocked_tools": self.policy.blocked_tools,
379
+ },
380
+ }
381
+
382
+ def health_check(self) -> dict[str, Any]:
383
+ """Return adapter health status.
384
+
385
+ Returns:
386
+ A dict with ``status``, ``backend``, ``last_error``, and
387
+ ``uptime_seconds`` keys.
388
+ """
389
+ uptime: float = time.monotonic() - self._start_time
390
+ status: str = "degraded" if self._last_error else "healthy"
391
+ return {
392
+ "status": status,
393
+ "backend": "openai_agents_sdk",
394
+ "backend_connected": bool(self._wrapped_agents),
395
+ "last_error": self._last_error,
396
+ "uptime_seconds": round(uptime, 2),
397
+ }
398
+
399
+
400
+ # Convenience exports
401
+ __all__ = [
402
+ "OpenAIAgentsKernel",
403
+ "GovernancePolicy",
404
+ "ExecutionContext",
405
+ "PolicyViolationError",
406
+ ]
@@ -0,0 +1,171 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Policy Inheritance and Composition
5
+
6
+ Utilities for merging, inheriting, and overriding GovernancePolicy instances.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import asdict, fields
12
+ from typing import Any
13
+
14
+ from .base import GovernancePolicy
15
+
16
+ # Fields that use "most restrictive" (min) merging
17
+ _MIN_FIELDS = {"max_tokens", "max_tool_calls", "max_concurrent", "timeout_seconds"}
18
+
19
+ # Fields that use "most restrictive" (truthy wins) merging
20
+ _BOOL_RESTRICTIVE = {"require_human_approval", "log_all_calls"}
21
+
22
+ # List fields with special merge semantics
23
+ _UNION_LIST_FIELDS = {"blocked_patterns"}
24
+ _INTERSECT_LIST_FIELDS = {"allowed_tools"}
25
+
26
+
27
+ def override_policy(base: GovernancePolicy, **kwargs: Any) -> GovernancePolicy:
28
+ """Create a copy of *base* with the given field overrides applied."""
29
+ data = asdict(base)
30
+ data.update(kwargs)
31
+ return GovernancePolicy(**data)
32
+
33
+
34
+ def compose_policies(*policies: GovernancePolicy) -> GovernancePolicy:
35
+ """Merge multiple policies using most-restrictive-wins semantics.
36
+
37
+ - ``max_tokens``, ``max_tool_calls``, ``max_concurrent``, ``timeout_seconds``:
38
+ smallest value wins.
39
+ - ``blocked_patterns``: union of all lists.
40
+ - ``allowed_tools``: intersection when both specify; single list kept as-is.
41
+ - ``version``: highest version string (lexicographic).
42
+ - ``name``: names joined with " + ".
43
+ - ``require_human_approval``, ``log_all_calls``: ``True`` if *any* policy
44
+ sets them.
45
+ """
46
+ if not policies:
47
+ raise ValueError("compose_policies requires at least one policy")
48
+ if len(policies) == 1:
49
+ return override_policy(policies[0])
50
+
51
+ result = asdict(policies[0])
52
+
53
+ for policy in policies[1:]:
54
+ other = asdict(policy)
55
+
56
+ # Name
57
+ result["name"] = result["name"] + " + " + other["name"]
58
+
59
+ # Most-restrictive numeric fields
60
+ for f in _MIN_FIELDS:
61
+ result[f] = min(result[f], other[f])
62
+
63
+ # Boolean restrictive fields
64
+ for f in _BOOL_RESTRICTIVE:
65
+ result[f] = result[f] or other[f]
66
+
67
+ # Union list fields
68
+ for f in _UNION_LIST_FIELDS:
69
+ combined = list(result[f])
70
+ for item in other[f]:
71
+ if item not in combined:
72
+ combined.append(item)
73
+ result[f] = combined
74
+
75
+ # Intersect list fields (allowed_tools)
76
+ for f in _INTERSECT_LIST_FIELDS:
77
+ left = result[f]
78
+ right = other[f]
79
+ if left and right:
80
+ result[f] = [t for t in left if t in right]
81
+ elif right:
82
+ result[f] = list(right)
83
+ # if only left has values, keep them as-is
84
+
85
+ # Highest version
86
+ if other["version"] > result["version"]:
87
+ result["version"] = other["version"]
88
+
89
+ # Safety thresholds – most restrictive
90
+ result["confidence_threshold"] = max(
91
+ result["confidence_threshold"], other["confidence_threshold"]
92
+ )
93
+ result["drift_threshold"] = min(
94
+ result["drift_threshold"], other["drift_threshold"]
95
+ )
96
+
97
+ # Checkpoint frequency – more frequent wins
98
+ result["checkpoint_frequency"] = min(
99
+ result["checkpoint_frequency"], other["checkpoint_frequency"]
100
+ )
101
+
102
+ # Backpressure threshold – lower is more restrictive
103
+ result["backpressure_threshold"] = min(
104
+ result["backpressure_threshold"], other["backpressure_threshold"]
105
+ )
106
+
107
+ return GovernancePolicy(**result)
108
+
109
+
110
+ class PolicyHierarchy:
111
+ """Tree-structured policy inheritance.
112
+
113
+ A hierarchy node wraps a *base* (parent) policy and can produce child
114
+ policies that inherit from it, with optional overrides.
115
+ """
116
+
117
+ def __init__(self, base: GovernancePolicy) -> None:
118
+ self._base = base
119
+
120
+ @property
121
+ def policy(self) -> GovernancePolicy:
122
+ """The base policy of this hierarchy node."""
123
+ return self._base
124
+
125
+ def extend(self, **overrides: Any) -> GovernancePolicy:
126
+ """Return a new policy that inherits from the base with *overrides*."""
127
+ return override_policy(self._base, **overrides)
128
+
129
+ def child(self, name: str, **overrides: Any) -> PolicyHierarchy:
130
+ """Create a child hierarchy node inheriting from this one."""
131
+ child_policy = self.extend(name=name, **overrides)
132
+ return PolicyHierarchy(child_policy)
133
+
134
+ def chain(self, *policies: GovernancePolicy) -> GovernancePolicy:
135
+ """Apply policies in priority order on top of the base.
136
+
137
+ Later policies win for simple scalar fields; list fields are unioned.
138
+ """
139
+ if not policies:
140
+ return override_policy(self._base)
141
+
142
+ result = asdict(self._base)
143
+
144
+ for policy in policies:
145
+ other = asdict(policy)
146
+ for f in fields(GovernancePolicy):
147
+ key = f.name
148
+ val = other[key]
149
+ if key == "name":
150
+ continue # handled separately
151
+ if key in _UNION_LIST_FIELDS:
152
+ combined = list(result[key])
153
+ for item in val:
154
+ if item not in combined:
155
+ combined.append(item)
156
+ result[key] = combined
157
+ elif key in _INTERSECT_LIST_FIELDS:
158
+ left = result[key]
159
+ right = val
160
+ if left and right:
161
+ result[key] = [t for t in left if t in right]
162
+ elif right:
163
+ result[key] = list(right)
164
+ else:
165
+ result[key] = val
166
+
167
+ # Build composite name
168
+ names = [self._base.name] + [p.name for p in policies]
169
+ result["name"] = " + ".join(names)
170
+
171
+ return GovernancePolicy(**result)