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,115 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Declarative policy schema for Agent-OS governance.
5
+
6
+ Defines PolicyDocument and related models that represent policies as
7
+ pure data (JSON/YAML) rather than coupling structure with evaluation logic.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from enum import Enum
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ from pydantic import BaseModel, Field
18
+
19
+
20
+ class PolicyOperator(str, Enum):
21
+ """Comparison operators for policy conditions."""
22
+
23
+ EQ = "eq"
24
+ NE = "ne"
25
+ GT = "gt"
26
+ LT = "lt"
27
+ GTE = "gte"
28
+ LTE = "lte"
29
+ IN = "in"
30
+ MATCHES = "matches"
31
+ CONTAINS = "contains"
32
+
33
+
34
+ class PolicyAction(str, Enum):
35
+ """Actions a policy rule can prescribe."""
36
+
37
+ ALLOW = "allow"
38
+ DENY = "deny"
39
+ AUDIT = "audit"
40
+ BLOCK = "block"
41
+
42
+
43
+ class PolicyCondition(BaseModel):
44
+ """A single condition evaluated against execution context."""
45
+
46
+ field: str = Field(..., description="Context field, e.g. 'tool_name', 'token_count'")
47
+ operator: PolicyOperator = Field(..., description="Comparison operator")
48
+ value: Any = Field(..., description="Value to compare against")
49
+
50
+
51
+ class PolicyRule(BaseModel):
52
+ """A single governance rule within a policy document."""
53
+
54
+ name: str
55
+ condition: PolicyCondition
56
+ action: PolicyAction
57
+ priority: int = Field(default=0, description="Higher priority rules are evaluated first")
58
+ message: str = Field(default="", description="Human-readable explanation")
59
+
60
+
61
+ class PolicyDefaults(BaseModel):
62
+ """Default settings applied when no rule matches."""
63
+
64
+ action: PolicyAction = PolicyAction.ALLOW
65
+ max_tokens: int = 4096
66
+ max_tool_calls: int = 10
67
+ confidence_threshold: float = 0.8
68
+
69
+
70
+ class PolicyDocument(BaseModel):
71
+ """Top-level declarative policy document."""
72
+
73
+ version: str = "1.0"
74
+ name: str = "unnamed"
75
+ description: str = ""
76
+ rules: list[PolicyRule] = Field(default_factory=list)
77
+ defaults: PolicyDefaults = Field(default_factory=PolicyDefaults)
78
+
79
+ @classmethod
80
+ def from_yaml(cls, path: str | Path) -> PolicyDocument:
81
+ """Load a PolicyDocument from a YAML file."""
82
+ try:
83
+ import yaml
84
+ except ImportError as exc:
85
+ raise ImportError("pyyaml is required: pip install pyyaml") from exc
86
+
87
+ path = Path(path)
88
+ with open(path) as f:
89
+ data = yaml.safe_load(f)
90
+ return cls.model_validate(data)
91
+
92
+ def to_yaml(self, path: str | Path) -> None:
93
+ """Serialize this PolicyDocument to a YAML file."""
94
+ try:
95
+ import yaml
96
+ except ImportError as exc:
97
+ raise ImportError("pyyaml is required: pip install pyyaml") from exc
98
+
99
+ path = Path(path)
100
+ with open(path, "w") as f:
101
+ yaml.dump(self.model_dump(mode="json"), f, default_flow_style=False, sort_keys=False)
102
+
103
+ @classmethod
104
+ def from_json(cls, path: str | Path) -> PolicyDocument:
105
+ """Load a PolicyDocument from a JSON file."""
106
+ path = Path(path)
107
+ with open(path) as f:
108
+ data = json.load(f)
109
+ return cls.model_validate(data)
110
+
111
+ def to_json(self, path: str | Path) -> None:
112
+ """Serialize this PolicyDocument to a JSON file."""
113
+ path = Path(path)
114
+ with open(path, "w") as f:
115
+ json.dump(self.model_dump(mode="json"), f, indent=2)
@@ -0,0 +1,331 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Cross-project shared policy language for Agent-OS and Agent-Mesh.
5
+
6
+ Provides a unified governance schema (SharedPolicySchema) with rules,
7
+ conditions, and an evaluator that works across both projects. Includes
8
+ YAML serialization and a bridge to the existing PolicyDocument format.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ from dataclasses import dataclass, field
15
+ from datetime import datetime, timezone
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ from pydantic import BaseModel, Field
20
+
21
+ from .schema import (
22
+ PolicyAction,
23
+ PolicyCondition,
24
+ PolicyDocument,
25
+ PolicyOperator,
26
+ PolicyRule,
27
+ )
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # Enums / literals kept as plain strings for cross-project portability
31
+ # ---------------------------------------------------------------------------
32
+
33
+ VALID_SCOPES = ("agent", "tool", "flow", "mesh")
34
+ VALID_ACTIONS = ("allow", "deny", "audit", "escalate", "rate_limit")
35
+ VALID_OPERATORS = ("eq", "ne", "in", "not_in", "gt", "lt", "matches")
36
+
37
+
38
+ # ---------------------------------------------------------------------------
39
+ # Core dataclasses
40
+ # ---------------------------------------------------------------------------
41
+
42
+
43
+ @dataclass
44
+ class Condition:
45
+ """A single predicate evaluated against an execution context."""
46
+
47
+ field: str
48
+ operator: str
49
+ value: Any
50
+
51
+ def __post_init__(self) -> None:
52
+ if self.operator not in VALID_OPERATORS:
53
+ raise ValueError(
54
+ f"Invalid operator '{self.operator}', must be one of {VALID_OPERATORS}"
55
+ )
56
+
57
+
58
+ @dataclass
59
+ class SharedPolicyRule:
60
+ """A single governance rule within a shared policy."""
61
+
62
+ id: str
63
+ action: str
64
+ conditions: list[Condition] = field(default_factory=list)
65
+ priority: int = 0
66
+
67
+ def __post_init__(self) -> None:
68
+ if self.action not in VALID_ACTIONS:
69
+ raise ValueError(
70
+ f"Invalid action '{self.action}', must be one of {VALID_ACTIONS}"
71
+ )
72
+
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Schema model (Pydantic for validation & serialization)
76
+ # ---------------------------------------------------------------------------
77
+
78
+
79
+ class SharedPolicySchema(BaseModel):
80
+ """Unified policy schema that works across Agent-OS and Agent-Mesh."""
81
+
82
+ version: str = "1.0"
83
+ name: str
84
+ description: str = ""
85
+ scope: str
86
+ rules: list[dict[str, Any]] = Field(default_factory=list)
87
+ metadata: dict[str, Any] = Field(default_factory=dict)
88
+
89
+ def model_post_init(self, __context: Any) -> None:
90
+ if self.scope not in VALID_SCOPES:
91
+ raise ValueError(
92
+ f"Invalid scope '{self.scope}', must be one of {VALID_SCOPES}"
93
+ )
94
+
95
+ def parsed_rules(self) -> list[SharedPolicyRule]:
96
+ """Deserialize raw rule dicts into SharedPolicyRule objects."""
97
+ result: list[SharedPolicyRule] = []
98
+ for raw in self.rules:
99
+ conditions = [
100
+ Condition(field=c["field"], operator=c["operator"], value=c["value"])
101
+ for c in raw.get("conditions", [])
102
+ ]
103
+ result.append(
104
+ SharedPolicyRule(
105
+ id=raw["id"],
106
+ action=raw["action"],
107
+ conditions=conditions,
108
+ priority=raw.get("priority", 0),
109
+ )
110
+ )
111
+ return result
112
+
113
+ # -- YAML I/O ----------------------------------------------------------
114
+
115
+ @classmethod
116
+ def from_yaml(cls, path: str | Path) -> SharedPolicySchema:
117
+ """Load a SharedPolicySchema from a YAML file."""
118
+ try:
119
+ import yaml
120
+ except ImportError as exc:
121
+ raise ImportError("pyyaml is required: pip install pyyaml") from exc
122
+
123
+ path = Path(path)
124
+ with open(path) as f:
125
+ data = yaml.safe_load(f)
126
+ return cls.model_validate(data)
127
+
128
+ def to_yaml(self, path: str | Path) -> None:
129
+ """Serialize this SharedPolicySchema to a YAML file."""
130
+ try:
131
+ import yaml
132
+ except ImportError as exc:
133
+ raise ImportError("pyyaml is required: pip install pyyaml") from exc
134
+
135
+ path = Path(path)
136
+ with open(path, "w") as f:
137
+ yaml.dump(
138
+ self.model_dump(mode="json"),
139
+ f,
140
+ default_flow_style=False,
141
+ sort_keys=False,
142
+ )
143
+
144
+
145
+ # ---------------------------------------------------------------------------
146
+ # Decision
147
+ # ---------------------------------------------------------------------------
148
+
149
+
150
+ @dataclass
151
+ class SharedPolicyDecision:
152
+ """Result of evaluating shared policy rules against a context."""
153
+
154
+ allowed: bool = True
155
+ action: str = "allow"
156
+ matched_rule_id: str | None = None
157
+ reason: str = "No rules matched; default allow"
158
+ audit: dict[str, Any] = field(default_factory=dict)
159
+
160
+
161
+ # ---------------------------------------------------------------------------
162
+ # Evaluator
163
+ # ---------------------------------------------------------------------------
164
+
165
+
166
+ class SharedPolicyEvaluator:
167
+ """Evaluates SharedPolicyRules against an execution context dict."""
168
+
169
+ def evaluate(
170
+ self,
171
+ context: dict[str, Any],
172
+ rules: list[SharedPolicyRule],
173
+ ) -> SharedPolicyDecision:
174
+ """Evaluate *rules* against *context*, returning a decision.
175
+
176
+ Rules are sorted by priority descending. The first rule whose
177
+ **all** conditions match determines the outcome.
178
+ """
179
+ sorted_rules = sorted(rules, key=lambda r: r.priority, reverse=True)
180
+
181
+ for rule in sorted_rules:
182
+ if all(_eval_condition(c, context) for c in rule.conditions):
183
+ allowed = rule.action in ("allow", "audit")
184
+ return SharedPolicyDecision(
185
+ allowed=allowed,
186
+ action=rule.action,
187
+ matched_rule_id=rule.id,
188
+ reason=f"Matched rule '{rule.id}'",
189
+ audit={
190
+ "rule_id": rule.id,
191
+ "action": rule.action,
192
+ "context_snapshot": context,
193
+ "timestamp": datetime.now(timezone.utc).isoformat(),
194
+ },
195
+ )
196
+
197
+ return SharedPolicyDecision()
198
+
199
+
200
+ def _eval_condition(condition: Condition, context: dict[str, Any]) -> bool:
201
+ """Evaluate a single Condition against the context."""
202
+ ctx_value = context.get(condition.field)
203
+ if ctx_value is None:
204
+ return False
205
+
206
+ op = condition.operator
207
+ target = condition.value
208
+
209
+ if op == "eq":
210
+ return ctx_value == target # type: ignore[no-any-return]
211
+ if op == "ne":
212
+ return ctx_value != target # type: ignore[no-any-return]
213
+ if op == "gt":
214
+ return ctx_value > target # type: ignore[no-any-return]
215
+ if op == "lt":
216
+ return ctx_value < target # type: ignore[no-any-return]
217
+ if op == "in":
218
+ return ctx_value in target # type: ignore[no-any-return]
219
+ if op == "not_in":
220
+ return ctx_value not in target # type: ignore[no-any-return]
221
+ if op == "matches":
222
+ return bool(re.search(str(target), str(ctx_value)))
223
+
224
+ return False
225
+
226
+
227
+ # ---------------------------------------------------------------------------
228
+ # Bridge helpers — SharedPolicySchema <-> PolicyDocument
229
+ # ---------------------------------------------------------------------------
230
+
231
+ _ACTION_MAP_TO_POLICY: dict[str, PolicyAction] = {
232
+ "allow": PolicyAction.ALLOW,
233
+ "deny": PolicyAction.DENY,
234
+ "audit": PolicyAction.AUDIT,
235
+ "escalate": PolicyAction.BLOCK,
236
+ "rate_limit": PolicyAction.BLOCK,
237
+ }
238
+
239
+ _OPERATOR_MAP_TO_POLICY: dict[str, PolicyOperator] = {
240
+ "eq": PolicyOperator.EQ,
241
+ "ne": PolicyOperator.NE,
242
+ "gt": PolicyOperator.GT,
243
+ "lt": PolicyOperator.LT,
244
+ "in": PolicyOperator.IN,
245
+ "not_in": PolicyOperator.NE,
246
+ "matches": PolicyOperator.MATCHES,
247
+ }
248
+
249
+ _ACTION_MAP_FROM_POLICY: dict[PolicyAction, str] = {
250
+ PolicyAction.ALLOW: "allow",
251
+ PolicyAction.DENY: "deny",
252
+ PolicyAction.AUDIT: "audit",
253
+ PolicyAction.BLOCK: "deny",
254
+ }
255
+
256
+ _OPERATOR_MAP_FROM_POLICY: dict[PolicyOperator, str] = {
257
+ PolicyOperator.EQ: "eq",
258
+ PolicyOperator.NE: "ne",
259
+ PolicyOperator.GT: "gt",
260
+ PolicyOperator.LT: "lt",
261
+ PolicyOperator.GTE: "gt",
262
+ PolicyOperator.LTE: "lt",
263
+ PolicyOperator.IN: "in",
264
+ PolicyOperator.CONTAINS: "matches",
265
+ PolicyOperator.MATCHES: "matches",
266
+ }
267
+
268
+
269
+ def shared_to_policy_document(schema: SharedPolicySchema) -> PolicyDocument:
270
+ """Convert a SharedPolicySchema into the existing PolicyDocument format."""
271
+ doc_rules: list[PolicyRule] = []
272
+ for rule in schema.parsed_rules():
273
+ if not rule.conditions:
274
+ continue
275
+ first_cond = rule.conditions[0]
276
+ doc_rules.append(
277
+ PolicyRule(
278
+ name=rule.id,
279
+ condition=PolicyCondition(
280
+ field=first_cond.field,
281
+ operator=_OPERATOR_MAP_TO_POLICY.get(
282
+ first_cond.operator, PolicyOperator.EQ
283
+ ),
284
+ value=first_cond.value,
285
+ ),
286
+ action=_ACTION_MAP_TO_POLICY.get(rule.action, PolicyAction.DENY),
287
+ priority=rule.priority,
288
+ message=f"Converted from shared rule '{rule.id}'",
289
+ )
290
+ )
291
+
292
+ return PolicyDocument(
293
+ version=schema.version,
294
+ name=schema.name,
295
+ description=schema.description,
296
+ rules=doc_rules,
297
+ )
298
+
299
+
300
+ def policy_document_to_shared(
301
+ doc: PolicyDocument,
302
+ scope: str = "agent",
303
+ ) -> SharedPolicySchema:
304
+ """Convert an existing PolicyDocument into a SharedPolicySchema."""
305
+ raw_rules: list[dict[str, Any]] = []
306
+ for rule in doc.rules:
307
+ cond = rule.condition
308
+ raw_rules.append(
309
+ {
310
+ "id": rule.name,
311
+ "action": _ACTION_MAP_FROM_POLICY.get(rule.action, "deny"),
312
+ "priority": rule.priority,
313
+ "conditions": [
314
+ {
315
+ "field": cond.field,
316
+ "operator": _OPERATOR_MAP_FROM_POLICY.get(
317
+ cond.operator, "eq"
318
+ ),
319
+ "value": cond.value,
320
+ }
321
+ ],
322
+ }
323
+ )
324
+
325
+ return SharedPolicySchema(
326
+ version=doc.version,
327
+ name=doc.name,
328
+ description=doc.description,
329
+ scope=scope,
330
+ rules=raw_rules,
331
+ )