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
agent_os/server/app.py ADDED
@@ -0,0 +1,277 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """FastAPI application for Agent OS governance API."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ import os
9
+ import time
10
+ from datetime import datetime, timezone
11
+ from typing import Any
12
+
13
+ from fastapi import FastAPI, HTTPException, Query, Request
14
+ from fastapi.middleware.cors import CORSMiddleware
15
+ from fastapi.responses import JSONResponse
16
+
17
+ from agent_os.server.models import (
18
+ DetectBatchRequest,
19
+ DetectInjectionRequest,
20
+ DetectionBatchResponse,
21
+ DetectionResponse,
22
+ ErrorResponse,
23
+ ExecuteRequest,
24
+ ExecuteResponse,
25
+ HealthResponse,
26
+ MetricsResponse,
27
+ )
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ def _detection_result_to_response(result: Any) -> DetectionResponse:
33
+ """Convert a ``DetectionResult`` dataclass to a Pydantic response."""
34
+ return DetectionResponse(
35
+ is_injection=result.is_injection,
36
+ threat_level=result.threat_level.value,
37
+ injection_type=result.injection_type.value if result.injection_type else None,
38
+ confidence=result.confidence,
39
+ matched_patterns=list(result.matched_patterns),
40
+ explanation=result.explanation,
41
+ )
42
+
43
+
44
+ class GovServer:
45
+ """High-level wrapper that owns the FastAPI app and its dependencies."""
46
+
47
+ def __init__(
48
+ self,
49
+ *,
50
+ title: str = "Agent OS Governance API",
51
+ version: str | None = None,
52
+ ) -> None:
53
+ from agent_os import __version__
54
+ from agent_os.health import HealthChecker
55
+ from agent_os.metrics import GovernanceMetrics
56
+ from agent_os.prompt_injection import DetectionConfig, PromptInjectionDetector
57
+
58
+ self._version = version or __version__
59
+ self._detector = PromptInjectionDetector(DetectionConfig(sensitivity="balanced"))
60
+ self._metrics = GovernanceMetrics()
61
+ self._health_checker = HealthChecker(version=self._version)
62
+ self._app = create_app(self, title=title)
63
+
64
+ @property
65
+ def app(self) -> FastAPI:
66
+ return self._app
67
+
68
+ @property
69
+ def detector(self) -> Any:
70
+ return self._detector
71
+
72
+ @property
73
+ def metrics(self) -> Any:
74
+ return self._metrics
75
+
76
+ @property
77
+ def health_checker(self) -> Any:
78
+ return self._health_checker
79
+
80
+
81
+ def create_app(
82
+ server: GovServer | None = None,
83
+ *,
84
+ title: str = "Agent OS Governance API",
85
+ ) -> FastAPI:
86
+ """Build and return the FastAPI application with all routes."""
87
+ from agent_os import __version__
88
+
89
+ version = server._version if server else __version__
90
+
91
+ app = FastAPI(
92
+ title=title,
93
+ version=version,
94
+ description="REST API for Agent OS governance operations.",
95
+ )
96
+
97
+ # -- CORS middleware ----------------------------------------------------
98
+ app.add_middleware(
99
+ CORSMiddleware,
100
+ allow_origins=os.environ.get("CORS_ALLOWED_ORIGINS", "http://localhost:3000,http://localhost:8080").split(","),
101
+ allow_credentials=True,
102
+ allow_methods=["*"],
103
+ allow_headers=["*"],
104
+ )
105
+
106
+ # -- request timing middleware -----------------------------------------
107
+ @app.middleware("http")
108
+ async def _timing_middleware(request: Request, call_next: Any) -> Any:
109
+ start = time.perf_counter()
110
+ response = await call_next(request)
111
+ elapsed_ms = (time.perf_counter() - start) * 1000.0
112
+ response.headers["X-Response-Time"] = f"{elapsed_ms:.2f}ms"
113
+ return response
114
+
115
+ # -- exception handler -------------------------------------------------
116
+ @app.exception_handler(Exception)
117
+ async def _global_exception_handler(request: Request, exc: Exception) -> JSONResponse:
118
+ logger.exception("Unhandled exception: %s", exc)
119
+ return JSONResponse(
120
+ status_code=500,
121
+ content=ErrorResponse(
122
+ detail=str(exc),
123
+ error_code="INTERNAL_ERROR",
124
+ ).model_dump(),
125
+ )
126
+
127
+ # ======================================================================
128
+ # Routes
129
+ # ======================================================================
130
+
131
+ @app.get("/")
132
+ async def root() -> dict:
133
+ """Root info endpoint."""
134
+ return {
135
+ "name": "Agent OS Governance API",
136
+ "version": version,
137
+ "docs": "/docs",
138
+ }
139
+
140
+ # -- health / readiness ------------------------------------------------
141
+
142
+ @app.get("/health", response_model=HealthResponse)
143
+ async def health() -> HealthResponse:
144
+ """Health check endpoint."""
145
+ if server:
146
+ report = server.health_checker.check_health()
147
+ return HealthResponse(
148
+ status=report.status.value,
149
+ components={
150
+ name: {
151
+ "status": comp.status.value,
152
+ "message": comp.message,
153
+ }
154
+ for name, comp in report.components.items()
155
+ },
156
+ timestamp=report.timestamp,
157
+ )
158
+ return HealthResponse(
159
+ status="healthy",
160
+ components={},
161
+ timestamp=datetime.now(timezone.utc).isoformat() + "Z",
162
+ )
163
+
164
+ @app.get("/ready")
165
+ async def ready() -> dict:
166
+ """Readiness probe."""
167
+ if server:
168
+ report = server.health_checker.check_ready()
169
+ if not report.is_ready():
170
+ raise HTTPException(status_code=503, detail="Not ready")
171
+ return {"ready": True}
172
+
173
+ # -- metrics -----------------------------------------------------------
174
+
175
+ @app.get("/api/v1/metrics", response_model=MetricsResponse)
176
+ async def get_metrics() -> MetricsResponse:
177
+ """Return governance metrics snapshot."""
178
+ if server:
179
+ snap = server.metrics.snapshot()
180
+ return MetricsResponse(
181
+ total_checks=snap["total_checks"],
182
+ violations=snap["violations"],
183
+ approvals=snap["approvals"],
184
+ blocked=snap["blocked"],
185
+ avg_latency_ms=snap["avg_latency_ms"],
186
+ )
187
+ return MetricsResponse()
188
+
189
+ # -- prompt injection detection ----------------------------------------
190
+
191
+ @app.post("/api/v1/detect/injection", response_model=DetectionResponse)
192
+ async def detect_injection(req: DetectInjectionRequest) -> DetectionResponse:
193
+ """Scan a single text for prompt injection."""
194
+ from agent_os.prompt_injection import DetectionConfig, PromptInjectionDetector
195
+
196
+ if server and req.sensitivity == server.detector._config.sensitivity:
197
+ detector = server.detector
198
+ else:
199
+ detector = PromptInjectionDetector(
200
+ DetectionConfig(sensitivity=req.sensitivity)
201
+ )
202
+
203
+ result = detector.detect(req.text, req.source, req.canary_tokens)
204
+ return _detection_result_to_response(result)
205
+
206
+ @app.post("/api/v1/detect/injection/batch", response_model=DetectionBatchResponse)
207
+ async def detect_injection_batch(req: DetectBatchRequest) -> DetectionBatchResponse:
208
+ """Scan multiple texts for prompt injection."""
209
+ from agent_os.prompt_injection import DetectionConfig, PromptInjectionDetector
210
+
211
+ if server and req.sensitivity == server.detector._config.sensitivity:
212
+ detector = server.detector
213
+ else:
214
+ detector = PromptInjectionDetector(
215
+ DetectionConfig(sensitivity=req.sensitivity)
216
+ )
217
+
218
+ inputs = [(item.get("text", ""), item.get("source", "api")) for item in req.inputs]
219
+ results = detector.detect_batch(inputs, req.canary_tokens)
220
+ responses = [_detection_result_to_response(r) for r in results]
221
+ injections = sum(1 for r in responses if r.is_injection)
222
+
223
+ return DetectionBatchResponse(
224
+ results=responses,
225
+ total=len(responses),
226
+ injections_found=injections,
227
+ )
228
+
229
+ # -- execute -----------------------------------------------------------
230
+
231
+ @app.post("/api/v1/execute", response_model=ExecuteResponse)
232
+ async def execute(req: ExecuteRequest) -> ExecuteResponse:
233
+ """Execute an action through the stateless kernel."""
234
+ from agent_os.stateless import ExecutionContext, StatelessKernel
235
+
236
+ kernel = StatelessKernel()
237
+ ctx = ExecutionContext(
238
+ agent_id=req.agent_id,
239
+ policies=req.policies,
240
+ )
241
+ try:
242
+ result = await kernel.execute(req.action, req.params, ctx)
243
+ return ExecuteResponse(
244
+ success=result.success,
245
+ data=result.data,
246
+ error=result.error,
247
+ signal=result.signal,
248
+ )
249
+ except Exception as exc:
250
+ return ExecuteResponse(
251
+ success=False,
252
+ error=str(exc),
253
+ signal="SIGTERM",
254
+ )
255
+
256
+ # -- audit -------------------------------------------------------------
257
+
258
+ @app.get("/api/v1/audit/injections")
259
+ async def audit_injections(limit: int = Query(default=50, ge=1, le=1000)) -> dict:
260
+ """Return recent injection audit log entries."""
261
+ records: list[dict] = []
262
+ if server:
263
+ for rec in server.detector.audit_log[-limit:]:
264
+ records.append({
265
+ "timestamp": rec.timestamp.isoformat(),
266
+ "input_hash": rec.input_hash,
267
+ "source": rec.source,
268
+ "is_injection": rec.result.is_injection,
269
+ "threat_level": rec.result.threat_level.value,
270
+ "injection_type": (
271
+ rec.result.injection_type.value if rec.result.injection_type else None
272
+ ),
273
+ "explanation": rec.result.explanation,
274
+ })
275
+ return {"records": records, "total": len(records)}
276
+
277
+ return app
@@ -0,0 +1,104 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """Pydantic v2 request/response models for Agent OS Governance API."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ # ---------------------------------------------------------------------------
12
+ # Request models
13
+ # ---------------------------------------------------------------------------
14
+
15
+ class ExecuteRequest(BaseModel):
16
+ """Request to execute an action through the stateless kernel."""
17
+
18
+ action: str = Field(..., description="Action to execute")
19
+ params: dict = Field(default_factory=dict, description="Action parameters")
20
+ agent_id: str = Field(..., description="Unique agent identifier")
21
+ policies: list[str] = Field(default_factory=list, description="Policy names to enforce")
22
+
23
+
24
+ class DetectInjectionRequest(BaseModel):
25
+ """Request to scan a single text for prompt injection."""
26
+
27
+ text: str = Field(..., description="Input text to screen")
28
+ source: str = Field(default="api", description="Source identifier")
29
+ canary_tokens: list[str] | None = Field(default=None, description="Canary tokens to check")
30
+ sensitivity: str = Field(default="balanced", description="Detection sensitivity")
31
+
32
+
33
+ class DetectBatchRequest(BaseModel):
34
+ """Request to scan multiple texts for prompt injection."""
35
+
36
+ inputs: list[dict] = Field(
37
+ ..., description="List of dicts with 'text' and optional 'source' keys"
38
+ )
39
+ canary_tokens: list[str] | None = Field(default=None, description="Canary tokens to check")
40
+ sensitivity: str = Field(default="balanced", description="Detection sensitivity")
41
+
42
+
43
+ class PolicyEvalRequest(BaseModel):
44
+ """Request to evaluate policies against a context."""
45
+
46
+ context: dict = Field(..., description="Execution context for policy evaluation")
47
+ policy_name: str | None = Field(default=None, description="Specific policy to evaluate")
48
+
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Response models
52
+ # ---------------------------------------------------------------------------
53
+
54
+ class ExecuteResponse(BaseModel):
55
+ """Response from stateless kernel execution."""
56
+
57
+ success: bool
58
+ data: Any = None
59
+ error: str | None = None
60
+ signal: str | None = None
61
+
62
+
63
+ class DetectionResponse(BaseModel):
64
+ """Response from prompt injection detection."""
65
+
66
+ is_injection: bool
67
+ threat_level: str
68
+ injection_type: str | None = None
69
+ confidence: float
70
+ matched_patterns: list[str] = Field(default_factory=list)
71
+ explanation: str = ""
72
+
73
+
74
+ class DetectionBatchResponse(BaseModel):
75
+ """Response from batch prompt injection detection."""
76
+
77
+ results: list[DetectionResponse]
78
+ total: int
79
+ injections_found: int
80
+
81
+
82
+ class HealthResponse(BaseModel):
83
+ """Health check response."""
84
+
85
+ status: str
86
+ components: dict = Field(default_factory=dict)
87
+ timestamp: str = ""
88
+
89
+
90
+ class MetricsResponse(BaseModel):
91
+ """Governance metrics snapshot."""
92
+
93
+ total_checks: int = 0
94
+ violations: int = 0
95
+ approvals: int = 0
96
+ blocked: int = 0
97
+ avg_latency_ms: float = 0.0
98
+
99
+
100
+ class ErrorResponse(BaseModel):
101
+ """Error response for failed requests."""
102
+
103
+ detail: str
104
+ error_code: str = "INTERNAL_ERROR"
@@ -0,0 +1,130 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """Shift-left compliance metrics.
4
+
5
+ Tracks where policy violations are caught in the development lifecycle
6
+ and computes a shift-left score: the earlier violations are detected,
7
+ the higher the score.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass, field
12
+ from datetime import datetime, timezone
13
+ from enum import Enum
14
+ from typing import Any
15
+
16
+
17
+ class ViolationStage(str, Enum):
18
+ """Stage in the development lifecycle where a violation was caught."""
19
+
20
+ PRE_COMMIT = "pre_commit" # IDE / local hooks
21
+ PR_CHECK = "pr_check" # Pull-request checks
22
+ CI_GATE = "ci_gate" # CI/CD pipeline gates
23
+ RUNTIME = "runtime" # Production / agent runtime
24
+
25
+
26
+ # Weights: earlier stages earn a higher shift-left contribution.
27
+ _STAGE_WEIGHTS: dict[ViolationStage, float] = {
28
+ ViolationStage.PRE_COMMIT: 1.0,
29
+ ViolationStage.PR_CHECK: 0.75,
30
+ ViolationStage.CI_GATE: 0.5,
31
+ ViolationStage.RUNTIME: 0.0,
32
+ }
33
+
34
+
35
+ @dataclass
36
+ class ViolationRecord:
37
+ """A single recorded policy violation."""
38
+
39
+ rule_name: str
40
+ stage: ViolationStage
41
+ timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
42
+ resolved: bool = False
43
+ message: str = ""
44
+
45
+
46
+ class ShiftLeftTracker:
47
+ """Tracks violation records and computes shift-left metrics."""
48
+
49
+ def __init__(self) -> None:
50
+ self._records: list[ViolationRecord] = []
51
+
52
+ def record(
53
+ self,
54
+ rule_name: str,
55
+ stage: ViolationStage,
56
+ *,
57
+ resolved: bool = False,
58
+ message: str = "",
59
+ ) -> ViolationRecord:
60
+ """Record a new violation and return the record."""
61
+ rec = ViolationRecord(
62
+ rule_name=rule_name,
63
+ stage=stage,
64
+ resolved=resolved,
65
+ message=message,
66
+ )
67
+ self._records.append(rec)
68
+ return rec
69
+
70
+ @property
71
+ def records(self) -> list[ViolationRecord]:
72
+ return list(self._records)
73
+
74
+ # ------------------------------------------------------------------
75
+ # Stage distribution
76
+ # ------------------------------------------------------------------
77
+
78
+ def stage_distribution(self) -> dict[str, int]:
79
+ """Return counts of violations per stage."""
80
+ dist: dict[str, int] = {s.value: 0 for s in ViolationStage}
81
+ for rec in self._records:
82
+ dist[rec.stage.value] += 1
83
+ return dist
84
+
85
+ # ------------------------------------------------------------------
86
+ # Shift-left score
87
+ # ------------------------------------------------------------------
88
+
89
+ def shift_left_score(self) -> float:
90
+ """Compute the shift-left score (0.0 - 1.0).
91
+
92
+ A score of 1.0 means every violation was caught at *pre_commit*.
93
+ A score of 0.0 means every violation was only caught at *runtime*
94
+ (or no violations were recorded).
95
+ """
96
+ if not self._records:
97
+ return 0.0
98
+ total_weight = sum(
99
+ _STAGE_WEIGHTS[rec.stage] for rec in self._records
100
+ )
101
+ return total_weight / len(self._records)
102
+
103
+ # ------------------------------------------------------------------
104
+ # Trend report
105
+ # ------------------------------------------------------------------
106
+
107
+ def trend_report(self) -> dict[str, Any]:
108
+ """Generate a summary trend report."""
109
+ total = len(self._records)
110
+ resolved = sum(1 for r in self._records if r.resolved)
111
+ return {
112
+ "total_violations": total,
113
+ "resolved": resolved,
114
+ "unresolved": total - resolved,
115
+ "shift_left_score": round(self.shift_left_score(), 3),
116
+ "stage_distribution": self.stage_distribution(),
117
+ "resolution_rate": round(resolved / total, 3) if total else 0.0,
118
+ }
119
+
120
+ # ------------------------------------------------------------------
121
+ # Helpers
122
+ # ------------------------------------------------------------------
123
+
124
+ def violations_for_rule(self, rule_name: str) -> list[ViolationRecord]:
125
+ """Return all violation records for a given rule name."""
126
+ return [r for r in self._records if r.rule_name == rule_name]
127
+
128
+ def clear(self) -> None:
129
+ """Remove all recorded violations."""
130
+ self._records.clear()