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,417 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ OpenAI Client Adapter - Drop-In Middleware for Agent Control Plane
5
+
6
+ This adapter wraps the OpenAI client to automatically intercept and govern
7
+ tool calls made by LLMs. It provides "zero-friction" integration - developers
8
+ can continue using the standard OpenAI SDK while benefiting from the control
9
+ plane's governance and safety features.
10
+
11
+ Usage:
12
+ from openai import OpenAI
13
+ from agent_control_plane import AgentControlPlane
14
+ from agent_control_plane.adapter import ControlPlaneAdapter
15
+
16
+ # Standard setup
17
+ client = OpenAI(api_key="your-key")
18
+ control_plane = AgentControlPlane()
19
+ agent_context = control_plane.create_agent("my-agent", permissions)
20
+
21
+ # Wrap with adapter
22
+ governed_client = ControlPlaneAdapter(
23
+ control_plane=control_plane,
24
+ agent_context=agent_context,
25
+ original_client=client
26
+ )
27
+
28
+ # Use exactly as you would use OpenAI client
29
+ response = governed_client.chat.completions.create(
30
+ model="gpt-4",
31
+ messages=[...],
32
+ tools=[...]
33
+ )
34
+ # Tool calls are automatically governed by the control plane!
35
+ """
36
+
37
+ from typing import Any, Dict, List, Optional, Callable
38
+ import json
39
+ import logging
40
+ from datetime import datetime
41
+
42
+ from .agent_kernel import ActionType, AgentContext
43
+ from .control_plane import AgentControlPlane
44
+
45
+
46
+ # Mapping from common OpenAI tool names to ActionType
47
+ DEFAULT_TOOL_MAPPING = {
48
+ # File operations
49
+ "read_file": ActionType.FILE_READ,
50
+ "write_file": ActionType.FILE_WRITE,
51
+ "file_read": ActionType.FILE_READ,
52
+ "file_write": ActionType.FILE_WRITE,
53
+
54
+ # Code execution
55
+ "execute_code": ActionType.CODE_EXECUTION,
56
+ "run_code": ActionType.CODE_EXECUTION,
57
+ "python": ActionType.CODE_EXECUTION,
58
+ "bash": ActionType.CODE_EXECUTION,
59
+ "code_interpreter": ActionType.CODE_EXECUTION,
60
+
61
+ # Database operations
62
+ "database_query": ActionType.DATABASE_QUERY,
63
+ "sql_query": ActionType.DATABASE_QUERY,
64
+ "db_query": ActionType.DATABASE_QUERY,
65
+ "database_write": ActionType.DATABASE_WRITE,
66
+ "sql_write": ActionType.DATABASE_WRITE,
67
+ "db_write": ActionType.DATABASE_WRITE,
68
+
69
+ # API calls
70
+ "api_call": ActionType.API_CALL,
71
+ "http_request": ActionType.API_CALL,
72
+ "make_request": ActionType.API_CALL,
73
+
74
+ # Workflow operations
75
+ "trigger_workflow": ActionType.WORKFLOW_TRIGGER,
76
+ "start_workflow": ActionType.WORKFLOW_TRIGGER,
77
+ }
78
+
79
+
80
+ class ChatCompletionsWrapper:
81
+ """
82
+ Wrapper for chat.completions that intercepts tool calls.
83
+
84
+ This class mimics the OpenAI client's chat.completions interface
85
+ while adding governance checks for tool calls.
86
+ """
87
+
88
+ def __init__(
89
+ self,
90
+ original_completions: Any,
91
+ control_plane: AgentControlPlane,
92
+ agent_context: AgentContext,
93
+ tool_mapping: Dict[str, ActionType],
94
+ logger: logging.Logger,
95
+ on_block: Optional[Callable] = None
96
+ ):
97
+ self.original = original_completions
98
+ self.control_plane = control_plane
99
+ self.agent_context = agent_context
100
+ self.tool_mapping = tool_mapping
101
+ self.logger = logger
102
+ self.on_block = on_block
103
+
104
+ def create(self, **kwargs) -> Any:
105
+ """
106
+ Create a chat completion with automatic tool call governance.
107
+
108
+ This method:
109
+ 1. Calls the OpenAI API to get the LLM's response
110
+ 2. Intercepts any tool_calls in the response
111
+ 3. Checks each tool call against the control plane
112
+ 4. Blocks or modifies tool calls that violate policies
113
+ 5. Returns the (possibly modified) response
114
+
115
+ Args:
116
+ **kwargs: All standard OpenAI chat.completions.create parameters
117
+
118
+ Returns:
119
+ The OpenAI ChatCompletion response, with tool calls governed
120
+ """
121
+ # 1. Let the LLM think - call the original OpenAI API
122
+ self.logger.debug(f"Agent {self.agent_context.agent_id}: Calling OpenAI API")
123
+ response = self.original.create(**kwargs)
124
+
125
+ # 2. Check if there are tool calls to intercept
126
+ if not hasattr(response, 'choices') or not response.choices:
127
+ return response
128
+
129
+ choice = response.choices[0]
130
+ if not hasattr(choice, 'message') or not hasattr(choice.message, 'tool_calls'):
131
+ return response
132
+
133
+ if not choice.message.tool_calls:
134
+ return response
135
+
136
+ # 3. Intercept and govern each tool call
137
+ self.logger.info(
138
+ f"Agent {self.agent_context.agent_id}: Intercepting {len(choice.message.tool_calls)} tool call(s)"
139
+ )
140
+
141
+ for tool_call in choice.message.tool_calls:
142
+ if not hasattr(tool_call, 'function'):
143
+ continue
144
+
145
+ tool_name = tool_call.function.name
146
+
147
+ # Parse arguments (they come as JSON string from OpenAI)
148
+ try:
149
+ tool_args = json.loads(tool_call.function.arguments) if tool_call.function.arguments else {}
150
+ except json.JSONDecodeError as e:
151
+ self.logger.warning(
152
+ f"Could not parse arguments for tool '{tool_name}': {tool_call.function.arguments}. "
153
+ f"Error: {e}. Using empty dict."
154
+ )
155
+ tool_args = {}
156
+
157
+ # Map tool name to ActionType
158
+ action_type = self._map_tool_to_action(tool_name)
159
+
160
+ if action_type is None:
161
+ self.logger.warning(f"Unknown tool '{tool_name}', allowing by default")
162
+ continue
163
+
164
+ # THE KERNEL CHECK - This is where governance happens
165
+ self.logger.debug(f"Checking permission for {tool_name} -> {action_type.value}")
166
+
167
+ # Check permission through control plane
168
+ check_result = self.control_plane.execute_action(
169
+ self.agent_context,
170
+ action_type,
171
+ tool_args
172
+ )
173
+
174
+ if not check_result['success']:
175
+ # Action is BLOCKED by the control plane
176
+ self.logger.warning(
177
+ f"BLOCKED: Agent {self.agent_context.agent_id} attempted {tool_name} "
178
+ f"but was denied: {check_result.get('error', 'Unknown reason')}"
179
+ )
180
+
181
+ # Overwrite the tool call with a "blocked" indicator
182
+ # The Mute Agent pattern: return NULL/minimal response
183
+ tool_call.function.name = "blocked_action"
184
+ tool_call.function.arguments = json.dumps({
185
+ "original_tool": tool_name,
186
+ "reason": "Action blocked by Agent Control Plane",
187
+ "error": check_result.get('error', 'Policy violation')
188
+ })
189
+
190
+ # Call the optional callback
191
+ if self.on_block:
192
+ self.on_block(tool_name, tool_args, check_result)
193
+ else:
194
+ self.logger.info(f"ALLOWED: {tool_name} for agent {self.agent_context.agent_id}")
195
+
196
+ return response
197
+
198
+ def _map_tool_to_action(self, tool_name: str) -> Optional[ActionType]:
199
+ """
200
+ Map an OpenAI tool name to an ActionType.
201
+
202
+ This uses both the provided mapping and pattern matching
203
+ to handle various naming conventions.
204
+
205
+ Args:
206
+ tool_name: The name of the tool from OpenAI
207
+
208
+ Returns:
209
+ ActionType if mapped, None if unknown
210
+ """
211
+ # Check exact match first
212
+ tool_name_lower = tool_name.lower()
213
+ if tool_name_lower in self.tool_mapping:
214
+ return self.tool_mapping[tool_name_lower]
215
+
216
+ # Pattern matching for common variations
217
+ if any(pattern in tool_name_lower for pattern in ['read', 'get', 'fetch', 'load']) and \
218
+ any(pattern in tool_name_lower for pattern in ['file', 'document']):
219
+ return ActionType.FILE_READ
220
+
221
+ if any(pattern in tool_name_lower for pattern in ['write', 'save', 'create', 'update']) and \
222
+ any(pattern in tool_name_lower for pattern in ['file', 'document']):
223
+ return ActionType.FILE_WRITE
224
+
225
+ if any(pattern in tool_name_lower for pattern in ['exec', 'run', 'execute', 'eval']) and \
226
+ any(pattern in tool_name_lower for pattern in ['code', 'python', 'script', 'command', 'bash']):
227
+ return ActionType.CODE_EXECUTION
228
+
229
+ if any(pattern in tool_name_lower for pattern in ['select', 'query', 'search']) and \
230
+ any(pattern in tool_name_lower for pattern in ['database', 'db', 'sql', 'table']):
231
+ return ActionType.DATABASE_QUERY
232
+
233
+ if any(pattern in tool_name_lower for pattern in ['insert', 'update', 'delete', 'drop', 'create', 'alter']) and \
234
+ any(pattern in tool_name_lower for pattern in ['database', 'db', 'sql', 'table']):
235
+ return ActionType.DATABASE_WRITE
236
+
237
+ if any(pattern in tool_name_lower for pattern in ['api', 'http', 'request', 'call', 'post', 'get']):
238
+ return ActionType.API_CALL
239
+
240
+ if any(pattern in tool_name_lower for pattern in ['workflow', 'trigger', 'pipeline']):
241
+ return ActionType.WORKFLOW_TRIGGER
242
+
243
+ return None
244
+
245
+
246
+ class ChatWrapper:
247
+ """Wrapper for chat namespace"""
248
+
249
+ def __init__(
250
+ self,
251
+ original_chat: Any,
252
+ control_plane: AgentControlPlane,
253
+ agent_context: AgentContext,
254
+ tool_mapping: Dict[str, ActionType],
255
+ logger: logging.Logger,
256
+ on_block: Optional[Callable] = None
257
+ ):
258
+ self.original = original_chat
259
+ self.completions = ChatCompletionsWrapper(
260
+ original_chat.completions,
261
+ control_plane,
262
+ agent_context,
263
+ tool_mapping,
264
+ logger,
265
+ on_block
266
+ )
267
+
268
+
269
+ class ControlPlaneAdapter:
270
+ """
271
+ OpenAI Client Adapter with Agent Control Plane Governance.
272
+
273
+ This class wraps an OpenAI client to provide automatic governance
274
+ of tool calls. It's designed as a drop-in replacement that requires
275
+ minimal code changes.
276
+
277
+ The adapter intercepts tool_calls in LLM responses and checks them
278
+ against the control plane's policies before allowing execution.
279
+ Blocked actions are replaced with error indicators following the
280
+ "Mute Agent" pattern.
281
+
282
+ Example:
283
+ # Before (ungovened):
284
+ client = OpenAI()
285
+ response = client.chat.completions.create(...)
286
+
287
+ # After (governed):
288
+ governed_client = ControlPlaneAdapter(control_plane, agent_context, client)
289
+ response = governed_client.chat.completions.create(...)
290
+ # Same API, but now with governance!
291
+ """
292
+
293
+ def __init__(
294
+ self,
295
+ control_plane: AgentControlPlane,
296
+ agent_context: AgentContext,
297
+ original_client: Any,
298
+ tool_mapping: Optional[Dict[str, ActionType]] = None,
299
+ on_block: Optional[Callable[[str, Dict, Dict], None]] = None,
300
+ logger: Optional[logging.Logger] = None
301
+ ):
302
+ """
303
+ Initialize the adapter.
304
+
305
+ Args:
306
+ control_plane: The AgentControlPlane instance for governance
307
+ agent_context: The AgentContext for the agent using this client
308
+ original_client: The original OpenAI client instance
309
+ tool_mapping: Optional custom mapping from tool names to ActionTypes
310
+ on_block: Optional callback called when an action is blocked
311
+ Signature: on_block(tool_name: str, tool_args: dict, result: dict)
312
+ logger: Optional logger instance
313
+ """
314
+ self.control_plane = control_plane
315
+ self.agent_context = agent_context
316
+ self.client = original_client
317
+ self.logger = logger or logging.getLogger("ControlPlaneAdapter")
318
+ self.on_block = on_block
319
+
320
+ # Merge default mapping with custom mapping
321
+ self.tool_mapping = DEFAULT_TOOL_MAPPING.copy()
322
+ if tool_mapping:
323
+ self.tool_mapping.update({k.lower(): v for k, v in tool_mapping.items()})
324
+
325
+ self.logger.info(
326
+ f"Initialized ControlPlaneAdapter for agent {agent_context.agent_id}"
327
+ )
328
+
329
+ @property
330
+ def chat(self) -> ChatWrapper:
331
+ """Access the wrapped chat API"""
332
+ return ChatWrapper(
333
+ self.client.chat,
334
+ self.control_plane,
335
+ self.agent_context,
336
+ self.tool_mapping,
337
+ self.logger,
338
+ self.on_block
339
+ )
340
+
341
+ def add_tool_mapping(self, tool_name: str, action_type: ActionType):
342
+ """
343
+ Add a custom tool name to ActionType mapping.
344
+
345
+ Args:
346
+ tool_name: The name of the tool as used in OpenAI
347
+ action_type: The ActionType it should map to
348
+ """
349
+ self.tool_mapping[tool_name.lower()] = action_type
350
+ self.logger.debug(f"Added tool mapping: {tool_name} -> {action_type.value}")
351
+
352
+ def get_statistics(self) -> Dict[str, Any]:
353
+ """
354
+ Get statistics about the adapter's activity.
355
+
356
+ Returns:
357
+ Dictionary with statistics from the control plane
358
+ """
359
+ return {
360
+ "agent_id": self.agent_context.agent_id,
361
+ "session_id": self.agent_context.session_id,
362
+ "control_plane_audit": self.control_plane.get_audit_log(limit=100),
363
+ "execution_history": self.control_plane.get_execution_history(
364
+ agent_id=self.agent_context.agent_id,
365
+ limit=100
366
+ )
367
+ }
368
+
369
+
370
+ def create_governed_client(
371
+ control_plane: AgentControlPlane,
372
+ agent_id: str,
373
+ openai_client: Any,
374
+ permissions: Optional[Dict[ActionType, Any]] = None,
375
+ tool_mapping: Optional[Dict[str, ActionType]] = None
376
+ ) -> ControlPlaneAdapter:
377
+ """
378
+ Convenience function to create a governed OpenAI client.
379
+
380
+ This creates both the agent in the control plane and the adapter,
381
+ providing a one-line setup for governed LLM interactions.
382
+
383
+ Args:
384
+ control_plane: The AgentControlPlane instance
385
+ agent_id: ID for the agent
386
+ openai_client: The OpenAI client to wrap
387
+ permissions: Optional permissions for the agent
388
+ tool_mapping: Optional custom tool name mappings
389
+
390
+ Returns:
391
+ A ControlPlaneAdapter ready to use
392
+
393
+ Example:
394
+ control_plane = AgentControlPlane()
395
+ openai_client = OpenAI(api_key="...")
396
+
397
+ governed = create_governed_client(
398
+ control_plane,
399
+ "my-agent",
400
+ openai_client,
401
+ permissions={
402
+ ActionType.FILE_READ: PermissionLevel.READ_ONLY,
403
+ ActionType.DATABASE_QUERY: PermissionLevel.READ_ONLY
404
+ }
405
+ )
406
+
407
+ # Use like normal OpenAI client
408
+ response = governed.chat.completions.create(...)
409
+ """
410
+ agent_context = control_plane.create_agent(agent_id, permissions)
411
+
412
+ return ControlPlaneAdapter(
413
+ control_plane=control_plane,
414
+ agent_context=agent_context,
415
+ original_client=openai_client,
416
+ tool_mapping=tool_mapping
417
+ )