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,422 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Semantic Policy Engine — Intent-based policy enforcement.
5
+
6
+ Classifies action+params into semantic intent categories and enforces
7
+ policies based on intent rather than brittle string patterns.
8
+
9
+ This is a heuristic classifier (no ML dependency). It can be upgraded
10
+ to a fine-tuned model later while keeping the same API.
11
+
12
+ Example:
13
+ >>> from agent_os.semantic_policy import SemanticPolicyEngine, IntentCategory
14
+ >>>
15
+ >>> engine = SemanticPolicyEngine()
16
+ >>> result = engine.classify("database_query", {"query": "DROP TABLE users"})
17
+ >>> result.category # IntentCategory.DESTRUCTIVE_DATA
18
+ >>> result.confidence # 0.95
19
+ >>>
20
+ >>> engine.check("database_query", {"query": "DROP TABLE users"}, deny=[IntentCategory.DESTRUCTIVE_DATA])
21
+ >>> # raises PolicyDenied
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import os
27
+ import re
28
+ import warnings
29
+ from dataclasses import dataclass, field
30
+ from enum import Enum
31
+ from typing import Any
32
+
33
+ # =============================================================================
34
+ # Disclaimer
35
+ # =============================================================================
36
+
37
+ _SAMPLE_DISCLAIMER = (
38
+ "\u26a0\ufe0f These are SAMPLE semantic policy signals provided as a starting "
39
+ "point. You MUST review, customise, and extend them for your specific use "
40
+ "case before deploying to production."
41
+ )
42
+
43
+ # =============================================================================
44
+ # Intent Categories
45
+ # =============================================================================
46
+
47
+
48
+ class IntentCategory(str, Enum):
49
+ """Semantic intent categories for agent actions."""
50
+ DESTRUCTIVE_DATA = "destructive_data" # DROP, DELETE, TRUNCATE, wipe
51
+ DATA_EXFILTRATION = "data_exfiltration" # bulk export, dump, copy-to-external
52
+ PRIVILEGE_ESCALATION = "privilege_escalation" # grant, sudo, chmod, admin
53
+ SYSTEM_MODIFICATION = "system_modification" # rm, shutdown, reboot, kill
54
+ CODE_EXECUTION = "code_execution" # exec, eval, subprocess, shell
55
+ NETWORK_ACCESS = "network_access" # fetch, curl, http, connect
56
+ DATA_READ = "data_read" # SELECT, get, read, list
57
+ DATA_WRITE = "data_write" # INSERT, UPDATE, create, write
58
+ BENIGN = "benign" # no risk signals detected
59
+
60
+
61
+ # =============================================================================
62
+ # Classification Result
63
+ # =============================================================================
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class IntentClassification:
68
+ """Result of semantic intent classification."""
69
+ category: IntentCategory
70
+ confidence: float # 0.0 to 1.0
71
+ matched_signals: tuple # signal keywords that matched
72
+ explanation: str = ""
73
+
74
+ @property
75
+ def is_dangerous(self) -> bool:
76
+ """True if intent is in a dangerous category with high confidence."""
77
+ return (
78
+ self.category
79
+ in {
80
+ IntentCategory.DESTRUCTIVE_DATA,
81
+ IntentCategory.DATA_EXFILTRATION,
82
+ IntentCategory.PRIVILEGE_ESCALATION,
83
+ IntentCategory.SYSTEM_MODIFICATION,
84
+ IntentCategory.CODE_EXECUTION,
85
+ }
86
+ and self.confidence >= 0.5
87
+ )
88
+
89
+
90
+ # =============================================================================
91
+ # Policy Denied Exception
92
+ # =============================================================================
93
+
94
+
95
+ class PolicyDenied(Exception):
96
+ """Raised when an action is denied by semantic policy."""
97
+
98
+ def __init__(self, classification: IntentClassification, policy_name: str = ""):
99
+ self.classification = classification
100
+ self.policy_name = policy_name
101
+ super().__init__(
102
+ f"Denied by {policy_name or 'semantic policy'}: "
103
+ f"intent={classification.category.value} "
104
+ f"confidence={classification.confidence:.0%} "
105
+ f"signals={classification.matched_signals}"
106
+ )
107
+
108
+
109
+ # =============================================================================
110
+ # Signal Definitions
111
+ # =============================================================================
112
+
113
+ # Each signal: (pattern_regex, weight, explanation)
114
+ _SIGNALS: dict[IntentCategory, list[tuple]] = {
115
+ IntentCategory.DESTRUCTIVE_DATA: [
116
+ (r"\bDROP\s+(TABLE|DATABASE|INDEX|VIEW|SCHEMA)\b", 0.9, "SQL DROP statement"),
117
+ (r"\bTRUNCATE\s+TABLE\b", 0.9, "SQL TRUNCATE"),
118
+ (r"\bDELETE\s+FROM\b.*\bWHERE\s+1\s*=\s*1\b", 0.95, "DELETE all rows"),
119
+ (r"\bDELETE\s+FROM\b(?!.*\bWHERE\b)", 0.85, "DELETE without WHERE"),
120
+ (r"\bDELETE\s+FROM\b", 0.4, "DELETE with filter"),
121
+ (r"\b(wipe|purge|destroy|erase|nuke)\b", 0.7, "destructive verb"),
122
+ (r"\bremove\s+(all|every|entire)\b", 0.75, "remove-all pattern"),
123
+ (r"\bformat\s+(disk|drive|partition)\b", 0.9, "disk format"),
124
+ (r"\bALTER\s+TABLE\b.*\bDROP\b", 0.8, "ALTER TABLE DROP column"),
125
+ ],
126
+ IntentCategory.DATA_EXFILTRATION: [
127
+ (r"\bSELECT\s+\*\s+FROM\b.*\bINTO\s+OUTFILE\b", 0.9, "SQL dump to file"),
128
+ (r"\bCOPY\s+.*\bTO\s+STDOUT\b", 0.8, "Postgres COPY to stdout"),
129
+ (r"\b(dump|export|backup)\s+(all|entire|full|complete)\b", 0.75, "full data export"),
130
+ (r"\b(upload|send|transmit)\s+.*\b(external|remote|s3|bucket)\b", 0.8, "external transfer"),
131
+ (r"\bpg_dump\b", 0.7, "database dump tool"),
132
+ (r"\bmysqldump\b", 0.7, "MySQL dump tool"),
133
+ (r"\b(wget|curl)\s+.*\|\s*", 0.6, "piped download"),
134
+ ],
135
+ IntentCategory.PRIVILEGE_ESCALATION: [
136
+ (r"\bGRANT\s+(ALL|SUPERUSER|ADMIN)\b", 0.9, "SQL GRANT elevated"),
137
+ (r"\bGRANT\b", 0.4, "SQL GRANT"),
138
+ (r"\bsudo\b", 0.7, "sudo invocation"),
139
+ (r"\bchmod\s+777\b", 0.8, "world-writable permissions"),
140
+ (r"\bchmod\s+[0-7]*[67][0-7]{2}\b", 0.5, "permissive chmod"),
141
+ (r"\b(escalat|elevat)\w*\s*(privilege|permission|access)\b", 0.8, "escalation language"),
142
+ (r"\bALTER\s+USER\b.*\bSUPERUSER\b", 0.9, "make superuser"),
143
+ (r"\bsu\s+-\b", 0.7, "switch user root"),
144
+ (r"\bpasswd\b", 0.5, "password change"),
145
+ ],
146
+ IntentCategory.SYSTEM_MODIFICATION: [
147
+ (r"\brm\s+-rf\b", 0.95, "recursive force delete"),
148
+ (r"\brm\s+-r\b", 0.7, "recursive delete"),
149
+ (r"\b(shutdown|reboot|halt|poweroff)\b", 0.8, "system power"),
150
+ (r"\bkill\s+-9\b", 0.7, "force kill process"),
151
+ (r"\bsystemctl\s+(stop|disable|mask)\b", 0.7, "stop system service"),
152
+ (r"\biptables\s+.*\bDROP\b", 0.8, "firewall drop rule"),
153
+ (r"\bregistry\s*(delete|modify)\b", 0.7, "Windows registry modification"),
154
+ (r"\bformat\s+[A-Z]:\b", 0.9, "format drive"),
155
+ ],
156
+ IntentCategory.CODE_EXECUTION: [
157
+ (r"\b(exec|eval)\s*\(", 0.8, "dynamic code execution"),
158
+ (r"\bsubprocess\b", 0.5, "subprocess call"),
159
+ (r"\bos\.system\b", 0.7, "os.system call"),
160
+ (r"\b__import__\b", 0.7, "dynamic import"),
161
+ (r"\bcompile\s*\(", 0.5, "compile code"),
162
+ (r"\bpickle\.loads\b", 0.7, "unsafe deserialization"),
163
+ ],
164
+ IntentCategory.NETWORK_ACCESS: [
165
+ (r"\b(fetch|requests\.get|requests\.post|urllib)\b", 0.4, "HTTP request"),
166
+ (r"\b(curl|wget)\s+http", 0.5, "command-line HTTP"),
167
+ (r"\bsocket\.connect\b", 0.6, "raw socket connection"),
168
+ (r"\bsmtplib\b", 0.5, "SMTP email"),
169
+ ],
170
+ IntentCategory.DATA_READ: [
171
+ (r"\bSELECT\b(?!.*\bINTO\b)", 0.6, "SQL SELECT"),
172
+ (r"\b(read|get|fetch|list|show|describe)\b", 0.3, "read verb"),
173
+ ],
174
+ IntentCategory.DATA_WRITE: [
175
+ (r"\b(INSERT|UPDATE)\b", 0.5, "SQL write"),
176
+ (r"\b(write|create|put|post|append)\b", 0.3, "write verb"),
177
+ ],
178
+ }
179
+
180
+
181
+ # =============================================================================
182
+ # Externalised configuration dataclass
183
+ # =============================================================================
184
+
185
+
186
+ @dataclass
187
+ class SemanticPolicyConfig:
188
+ """Structured configuration for semantic policy signals, loadable from YAML.
189
+
190
+ Attributes:
191
+ signals: Mapping of IntentCategory names to lists of
192
+ ``(pattern, weight, explanation)`` tuples.
193
+ disclaimer: Disclaimer text shown in logs.
194
+ """
195
+
196
+ signals: dict[str, list[tuple[str, float, str]]] = field(
197
+ default_factory=lambda: {
198
+ cat.value: [(p, w, e) for p, w, e in sigs]
199
+ for cat, sigs in _SIGNALS.items()
200
+ }
201
+ )
202
+ disclaimer: str = ""
203
+
204
+
205
+ def load_semantic_policy_config(path: str) -> SemanticPolicyConfig:
206
+ """Load semantic policy configuration from a YAML file.
207
+
208
+ Args:
209
+ path: Path to a YAML file with a ``signals`` section.
210
+
211
+ Returns:
212
+ SemanticPolicyConfig populated from the YAML data.
213
+
214
+ Raises:
215
+ FileNotFoundError: If the config file does not exist.
216
+ ValueError: If the YAML is missing the ``signals`` section.
217
+ """
218
+ import yaml
219
+
220
+ if not os.path.exists(path):
221
+ raise FileNotFoundError(f"Semantic policy config not found: {path}")
222
+
223
+ with open(path, "r", encoding="utf-8") as fh:
224
+ data = yaml.safe_load(fh.read())
225
+
226
+ if not isinstance(data, dict) or "signals" not in data:
227
+ raise ValueError(f"YAML file must contain a 'signals' section: {path}")
228
+
229
+ raw_signals = data["signals"]
230
+ signals: dict[str, list[tuple[str, float, str]]] = {}
231
+ for category_name, entries in raw_signals.items():
232
+ signals[category_name] = [
233
+ (entry["pattern"], float(entry["weight"]), entry.get("explanation", ""))
234
+ for entry in entries
235
+ ]
236
+
237
+ return SemanticPolicyConfig(
238
+ signals=signals,
239
+ disclaimer=data.get("disclaimer", ""),
240
+ )
241
+
242
+
243
+ # =============================================================================
244
+ # Semantic Policy Engine
245
+ # =============================================================================
246
+
247
+
248
+ class SemanticPolicyEngine:
249
+ """
250
+ Intent-based policy enforcement engine.
251
+
252
+ Classifies action+params into semantic intent categories using
253
+ weighted keyword signals, then enforces deny/allow policies.
254
+
255
+ This is a zero-dependency heuristic classifier designed to run in <1ms.
256
+ The API is stable — swap in an ML classifier later without changing callers.
257
+ """
258
+
259
+ def __init__(
260
+ self,
261
+ deny: list[IntentCategory] | None = None,
262
+ confidence_threshold: float = 0.5,
263
+ custom_signals: dict[IntentCategory, list[tuple]] | None = None,
264
+ config: SemanticPolicyConfig | None = None,
265
+ ):
266
+ """
267
+ Args:
268
+ deny: Intent categories to deny (default: all dangerous categories)
269
+ confidence_threshold: Minimum confidence to trigger deny (0.0-1.0)
270
+ custom_signals: Additional signal patterns to merge with defaults
271
+ config: Optional externalized configuration loaded via
272
+ ``load_semantic_policy_config()``.
273
+ """
274
+ if config is None and custom_signals is None:
275
+ warnings.warn(
276
+ "SemanticPolicyEngine() uses built-in sample rules that may not "
277
+ "cover all malicious intent patterns. For production use, load an "
278
+ "explicit config with load_semantic_policy_config(). "
279
+ "See examples/policies/semantic-policy.yaml for a sample configuration.",
280
+ stacklevel=2,
281
+ )
282
+ self.deny_categories: set[IntentCategory] = set(deny) if deny else {
283
+ IntentCategory.DESTRUCTIVE_DATA,
284
+ IntentCategory.DATA_EXFILTRATION,
285
+ IntentCategory.PRIVILEGE_ESCALATION,
286
+ IntentCategory.SYSTEM_MODIFICATION,
287
+ IntentCategory.CODE_EXECUTION,
288
+ }
289
+ self.confidence_threshold = confidence_threshold
290
+
291
+ # Build signals from config or defaults
292
+ if config is not None:
293
+ self.signals: dict[IntentCategory, list[tuple]] = {}
294
+ for cat_name, sigs in config.signals.items():
295
+ try:
296
+ cat = IntentCategory(cat_name)
297
+ except ValueError:
298
+ continue
299
+ self.signals[cat] = list(sigs)
300
+ else:
301
+ self.signals = {k: list(v) for k, v in _SIGNALS.items()}
302
+
303
+ if custom_signals:
304
+ for cat, sigs in custom_signals.items():
305
+ self.signals.setdefault(cat, []).extend(sigs)
306
+ # Pre-compile regexes for performance
307
+ self._compiled: dict[IntentCategory, list[tuple]] = {}
308
+ for cat, sigs in self.signals.items():
309
+ self._compiled[cat] = [
310
+ (re.compile(pattern, re.IGNORECASE), weight, explanation)
311
+ for pattern, weight, explanation in sigs
312
+ ]
313
+
314
+ def classify(
315
+ self, action: str, params: dict[str, Any]
316
+ ) -> IntentClassification:
317
+ """
318
+ Classify the semantic intent of an action+params.
319
+
320
+ Args:
321
+ action: Action name (e.g. "database_query")
322
+ params: Action parameters (e.g. {"query": "DROP TABLE users"})
323
+
324
+ Returns:
325
+ IntentClassification with category, confidence, and matched signals
326
+ """
327
+ # Build the text corpus to scan
328
+ text = self._build_text(action, params)
329
+
330
+ best_category = IntentCategory.BENIGN
331
+ best_confidence = 0.0
332
+ best_signals: list = []
333
+
334
+ for category, compiled_sigs in self._compiled.items():
335
+ matched = []
336
+ total_weight = 0.0
337
+
338
+ for regex, weight, explanation in compiled_sigs:
339
+ if regex.search(text):
340
+ matched.append(explanation)
341
+ total_weight = max(total_weight, weight)
342
+
343
+ if matched and total_weight > best_confidence:
344
+ best_category = category
345
+ best_confidence = total_weight
346
+ best_signals = matched
347
+
348
+ return IntentClassification(
349
+ category=best_category,
350
+ confidence=round(best_confidence, 3),
351
+ matched_signals=tuple(best_signals),
352
+ explanation=(
353
+ f"Detected {best_category.value} intent "
354
+ f"({best_confidence:.0%} confidence) "
355
+ f"from {len(best_signals)} signal(s)"
356
+ if best_signals
357
+ else "No risk signals detected"
358
+ ),
359
+ )
360
+
361
+ def check(
362
+ self,
363
+ action: str,
364
+ params: dict[str, Any],
365
+ *,
366
+ deny: list[IntentCategory] | None = None,
367
+ policy_name: str = "",
368
+ ) -> IntentClassification:
369
+ """
370
+ Classify and enforce — raises PolicyDenied if intent is denied.
371
+
372
+ Args:
373
+ action: Action name
374
+ params: Action parameters
375
+ deny: Override deny categories (uses engine defaults if None)
376
+ policy_name: Name for error messages
377
+
378
+ Returns:
379
+ IntentClassification if allowed
380
+
381
+ Raises:
382
+ PolicyDenied: If classified intent is in deny set above threshold
383
+ """
384
+ classification = self.classify(action, params)
385
+ deny_set = set(deny) if deny else self.deny_categories
386
+
387
+ if (
388
+ classification.category in deny_set
389
+ and classification.confidence >= self.confidence_threshold
390
+ ):
391
+ raise PolicyDenied(classification, policy_name)
392
+
393
+ return classification
394
+
395
+ @staticmethod
396
+ def _build_text(action: str, params: dict[str, Any]) -> str:
397
+ """Flatten action + params into a single searchable string."""
398
+ parts = [action]
399
+ for value in params.values():
400
+ if isinstance(value, str):
401
+ parts.append(value)
402
+ elif isinstance(value, (list, tuple)):
403
+ parts.extend(str(v) for v in value)
404
+ elif isinstance(value, dict):
405
+ parts.extend(str(v) for v in value.values())
406
+ else:
407
+ parts.append(str(value))
408
+ return " ".join(parts)
409
+
410
+
411
+ # =============================================================================
412
+ # Public API
413
+ # =============================================================================
414
+
415
+ __all__ = [
416
+ "IntentCategory",
417
+ "IntentClassification",
418
+ "PolicyDenied",
419
+ "SemanticPolicyConfig",
420
+ "SemanticPolicyEngine",
421
+ "load_semantic_policy_config",
422
+ ]
@@ -0,0 +1,15 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """Agent OS Governance API Server.
4
+
5
+ Provides a REST API for governance operations, enabling language-agnostic
6
+ access to Agent OS capabilities.
7
+ """
8
+
9
+ try:
10
+ from agent_os.server.app import GovServer, create_app
11
+ except ImportError: # pragma: no cover
12
+ GovServer = None # type: ignore[assignment,misc]
13
+ create_app = None # type: ignore[assignment]
14
+
15
+ __all__ = ["create_app", "GovServer"]
@@ -0,0 +1,25 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """Run Agent OS Governance API server."""
4
+
5
+ import argparse
6
+ import os
7
+
8
+ import uvicorn
9
+
10
+ from agent_os.server.app import GovServer
11
+
12
+
13
+ def main() -> None:
14
+ parser = argparse.ArgumentParser(description="Agent OS Governance API server")
15
+ parser.add_argument("--host", default=os.environ.get("HOST", "127.0.0.1"))
16
+ parser.add_argument("--port", type=int, default=int(os.environ.get("PORT", "8080")))
17
+ parser.add_argument("--log-level", default=os.environ.get("LOG_LEVEL", "info"))
18
+ args = parser.parse_args()
19
+
20
+ server = GovServer()
21
+ uvicorn.run(server.app, host=args.host, port=args.port, log_level=args.log_level)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()