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,449 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Path simulation system to test alternative solutions.
5
+ """
6
+
7
+ import logging
8
+ import uuid
9
+ from typing import List, Dict, Any, Optional
10
+
11
+ from .models import FailureAnalysis, SimulationResult, DiagnosisJSON, ShadowAgentResult, AgentFailure, CognitiveGlitch
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ShadowAgent:
17
+ """
18
+ Shadow Agent for counterfactual simulation.
19
+
20
+ Replays the user prompt with an injected hint in a sandbox environment.
21
+ This is "The Scientist" that verifies if the hint actually fixes the problem.
22
+ """
23
+
24
+ def __init__(self):
25
+ self.execution_history: List[ShadowAgentResult] = []
26
+
27
+ def replay_with_hint(
28
+ self,
29
+ original_prompt: str,
30
+ hint: str,
31
+ diagnosis: DiagnosisJSON,
32
+ failure: AgentFailure
33
+ ) -> ShadowAgentResult:
34
+ """
35
+ Replay the original prompt with an injected hint.
36
+
37
+ This simulates the agent executing with additional context/guidance.
38
+
39
+ Args:
40
+ original_prompt: Original user prompt that led to failure
41
+ hint: Hint to inject based on diagnosis
42
+ diagnosis: Cognitive glitch diagnosis
43
+ failure: Original failure for context
44
+
45
+ Returns:
46
+ ShadowAgentResult with execution outcome
47
+ """
48
+ shadow_id = f"shadow-{uuid.uuid4().hex[:8]}"
49
+
50
+ logger.info(f"Shadow agent {shadow_id} replaying with hint")
51
+
52
+ # Construct modified prompt with hint
53
+ modified_prompt = f"{original_prompt}\n\n{hint}"
54
+
55
+ # Simulate execution (in real system, this would run actual agent in sandbox)
56
+ execution_success, output, reasoning, action = self._simulate_execution(
57
+ modified_prompt, diagnosis, failure
58
+ )
59
+
60
+ # Verify the fix
61
+ verified = self._verify_fix(execution_success, action, failure)
62
+
63
+ result = ShadowAgentResult(
64
+ shadow_id=shadow_id,
65
+ original_prompt=original_prompt,
66
+ injected_hint=hint,
67
+ modified_prompt=modified_prompt,
68
+ execution_success=execution_success,
69
+ output=output,
70
+ reasoning_chain=reasoning,
71
+ action_taken=action,
72
+ verified=verified
73
+ )
74
+
75
+ self.execution_history.append(result)
76
+ logger.info(f"Shadow execution complete. Success: {execution_success}, Verified: {verified}")
77
+
78
+ return result
79
+
80
+ def _simulate_execution(
81
+ self,
82
+ prompt: str,
83
+ diagnosis: DiagnosisJSON,
84
+ failure: AgentFailure
85
+ ) -> tuple:
86
+ """
87
+ Simulate agent execution with the modified prompt.
88
+
89
+ In a real system, this would:
90
+ 1. Spin up a sandboxed agent instance
91
+ 2. Inject the hint into the system prompt or context
92
+ 3. Execute the agent with the original user prompt
93
+ 4. Capture the reasoning chain and action
94
+ 5. Check if the action would pass control plane checks
95
+ """
96
+ # Simulate reasoning chain with hint consideration
97
+ reasoning = [
98
+ "Parse user request",
99
+ f"Consider hint: {diagnosis.hint[:50]}...",
100
+ "Validate assumptions against provided context",
101
+ "Construct safe action"
102
+ ]
103
+
104
+ # Simulate a corrected action
105
+ # In reality, this would be the actual agent's output
106
+ if diagnosis.cognitive_glitch == CognitiveGlitch.HALLUCINATION:
107
+ # Agent would verify schema
108
+ action = {
109
+ "action": "execute_with_validation",
110
+ "validation": "schema_check_passed",
111
+ "safe_mode": True
112
+ }
113
+ success = True
114
+ output = "Action validated and executed successfully"
115
+ elif diagnosis.cognitive_glitch == CognitiveGlitch.PERMISSION_ERROR:
116
+ # Agent would check permissions first
117
+ action = {
118
+ "action": "check_permissions_then_execute",
119
+ "permission_validation": True
120
+ }
121
+ success = True
122
+ output = "Permissions validated, action executed"
123
+ else:
124
+ # Generic safe action
125
+ action = {
126
+ "action": "safe_execute",
127
+ "hint_applied": True
128
+ }
129
+ # Success based on diagnosis confidence (deterministic)
130
+ success = diagnosis.confidence > 0.7
131
+ output = "Action executed with safety checks" if success else "Action still failed"
132
+
133
+ return success, output, reasoning, action
134
+
135
+ def _verify_fix(self, success: bool, action: Optional[Dict], failure: AgentFailure) -> bool:
136
+ """
137
+ Verify that the fix actually works.
138
+
139
+ This is the key validation step - confirming the hint flips the outcome
140
+ from Fail to Pass.
141
+ """
142
+ if not success:
143
+ return False
144
+
145
+ # Check if action has safety mechanisms that original lacked
146
+ if action:
147
+ has_validation = any(
148
+ key in action for key in ["validation", "permission_validation", "schema_check", "safe_mode"]
149
+ )
150
+ return has_validation
151
+
152
+ return success
153
+
154
+
155
+ class PathSimulator:
156
+ """Simulates alternative paths to avoid failures."""
157
+
158
+ def __init__(self):
159
+ self.simulation_history: List[SimulationResult] = []
160
+ self.shadow_agent = ShadowAgent()
161
+ self.mcts_iterations = 5 # MCTS search iterations
162
+
163
+ def simulate(self, analysis: FailureAnalysis) -> SimulationResult:
164
+ """
165
+ Simulate an alternative path based on failure analysis.
166
+
167
+ Args:
168
+ analysis: The failure analysis containing suggested fixes
169
+
170
+ Returns:
171
+ SimulationResult with the alternative path and predicted outcome
172
+ """
173
+ logger.info(f"Simulating alternative path for agent {analysis.failure.agent_id}")
174
+
175
+ # Generate simulation ID
176
+ simulation_id = str(uuid.uuid4())
177
+
178
+ # Build alternative path from suggested fixes
179
+ alternative_path = self._build_alternative_path(analysis)
180
+
181
+ # Predict outcome
182
+ expected_outcome = self._predict_outcome(analysis, alternative_path)
183
+
184
+ # Calculate risk score
185
+ risk_score = self._calculate_risk(analysis, alternative_path)
186
+
187
+ # Estimate success rate
188
+ estimated_success_rate = self._estimate_success_rate(analysis, risk_score)
189
+
190
+ # Determine if simulation is successful
191
+ success = risk_score < 0.5 and estimated_success_rate > 0.7
192
+
193
+ result = SimulationResult(
194
+ simulation_id=simulation_id,
195
+ success=success,
196
+ alternative_path=alternative_path,
197
+ expected_outcome=expected_outcome,
198
+ risk_score=risk_score,
199
+ estimated_success_rate=estimated_success_rate
200
+ )
201
+
202
+ self.simulation_history.append(result)
203
+
204
+ if success:
205
+ logger.info(f"Simulation successful. Success rate: {estimated_success_rate:.2f}, Risk: {risk_score:.2f}")
206
+ else:
207
+ logger.warning(f"Simulation failed. Success rate: {estimated_success_rate:.2f}, Risk: {risk_score:.2f}")
208
+
209
+ return result
210
+
211
+ def simulate_counterfactual(
212
+ self,
213
+ diagnosis: DiagnosisJSON,
214
+ failure: AgentFailure
215
+ ) -> ShadowAgentResult:
216
+ """
217
+ Counterfactual simulation using Shadow Agent.
218
+
219
+ This is "The Simulator" - it replays the user prompt but injects a hint
220
+ based on the DiagnosisJSON. Uses MCTS-like approach to find minimal
221
+ change required to flip outcome from Fail to Pass.
222
+
223
+ Args:
224
+ diagnosis: Cognitive glitch diagnosis with hint
225
+ failure: Original failure with trace
226
+
227
+ Returns:
228
+ ShadowAgentResult showing if hint fixes the problem
229
+ """
230
+ logger.info("Starting counterfactual simulation with Shadow Agent")
231
+
232
+ if not failure.failure_trace:
233
+ logger.warning("No failure trace available for counterfactual simulation")
234
+ # Create a dummy result
235
+ return ShadowAgentResult(
236
+ shadow_id="shadow-no-trace",
237
+ original_prompt="No prompt available",
238
+ injected_hint=diagnosis.hint,
239
+ modified_prompt="No prompt available",
240
+ execution_success=False,
241
+ output="No trace available for simulation",
242
+ reasoning_chain=[],
243
+ action_taken=None,
244
+ verified=False
245
+ )
246
+
247
+ # Use MCTS-inspired approach: try multiple hint variations
248
+ best_result = self._mcts_search_minimal_hint(
249
+ failure.failure_trace.user_prompt,
250
+ diagnosis,
251
+ failure
252
+ )
253
+
254
+ return best_result
255
+
256
+ def _mcts_search_minimal_hint(
257
+ self,
258
+ prompt: str,
259
+ diagnosis: DiagnosisJSON,
260
+ failure: AgentFailure
261
+ ) -> ShadowAgentResult:
262
+ """
263
+ MCTS-inspired search for minimal hint that fixes the problem.
264
+
265
+ This searches for the minimal change required to flip the outcome.
266
+ In full MCTS, we'd build a tree of hint variations and explore/exploit,
267
+ but here we do a simplified version with multiple trials.
268
+ """
269
+ logger.info(f"MCTS search across {self.mcts_iterations} iterations")
270
+
271
+ hint_variations = self._generate_hint_variations(diagnosis.hint)
272
+ results = []
273
+
274
+ for i, hint in enumerate(hint_variations[:self.mcts_iterations]):
275
+ logger.debug(f"MCTS iteration {i+1}: Testing hint variation")
276
+ result = self.shadow_agent.replay_with_hint(
277
+ prompt, hint, diagnosis, failure
278
+ )
279
+ results.append(result)
280
+
281
+ # Early exit if we find a verified solution
282
+ if result.verified and result.execution_success:
283
+ logger.info(f"Found verified solution at iteration {i+1}")
284
+ break
285
+
286
+ # Select best result (verified + successful, or highest success)
287
+ best = max(
288
+ results,
289
+ key=lambda r: (r.verified, r.execution_success, len(r.reasoning_chain))
290
+ )
291
+
292
+ logger.info(f"MCTS search complete. Best result verified: {best.verified}")
293
+ return best
294
+
295
+ def _generate_hint_variations(self, base_hint: str) -> List[str]:
296
+ """
297
+ Generate variations of the hint for MCTS exploration.
298
+
299
+ This finds different ways to provide the same guidance,
300
+ searching for the minimal effective intervention.
301
+ """
302
+ variations = [base_hint] # Original hint
303
+
304
+ # Variation 1: More concise
305
+ if len(base_hint) > 50:
306
+ concise = base_hint.split(".")[0] + "."
307
+ variations.append(concise)
308
+
309
+ # Variation 2: More explicit
310
+ explicit = base_hint + " Double-check all assumptions."
311
+ variations.append(explicit)
312
+
313
+ # Variation 3: Focus on specific action
314
+ if "validate" in base_hint.lower():
315
+ variations.append("VALIDATION REQUIRED: " + base_hint)
316
+
317
+ # Variation 4: Minimal version
318
+ if "HINT:" in base_hint:
319
+ minimal = base_hint.replace("HINT: ", "")
320
+ variations.append(minimal)
321
+
322
+ return variations
323
+
324
+ def _build_alternative_path(self, analysis: FailureAnalysis) -> List[Dict[str, Any]]:
325
+ """Build an alternative execution path from suggested fixes."""
326
+ path = []
327
+ failure = analysis.failure
328
+
329
+ # Add validation step for control plane blocks
330
+ if failure.failure_type.value == "blocked_by_control_plane":
331
+ path.append({
332
+ "step": 1,
333
+ "action": "validate_permissions",
334
+ "description": "Check permissions before attempting action",
335
+ "params": {
336
+ "resource": failure.context.get("resource", "unknown"),
337
+ "action": failure.context.get("action", "unknown")
338
+ }
339
+ })
340
+
341
+ path.append({
342
+ "step": 2,
343
+ "action": "request_authorization",
344
+ "description": "Request proper authorization if needed",
345
+ "params": {
346
+ "required_permission": "resource_access"
347
+ }
348
+ })
349
+
350
+ path.append({
351
+ "step": 3,
352
+ "action": "safe_execute",
353
+ "description": "Execute action with safety checks",
354
+ "params": {
355
+ "original_action": failure.context.get("action", "unknown"),
356
+ "safety_mode": "enabled"
357
+ }
358
+ })
359
+
360
+ # Add timeout handling for timeout failures
361
+ elif failure.failure_type.value == "timeout":
362
+ path.append({
363
+ "step": 1,
364
+ "action": "set_timeout",
365
+ "description": "Configure appropriate timeout",
366
+ "params": {"timeout_seconds": 30}
367
+ })
368
+
369
+ path.append({
370
+ "step": 2,
371
+ "action": "add_progress_monitoring",
372
+ "description": "Add progress monitoring",
373
+ "params": {"check_interval_seconds": 5}
374
+ })
375
+
376
+ path.append({
377
+ "step": 3,
378
+ "action": "execute_with_timeout",
379
+ "description": "Execute with timeout handling",
380
+ "params": {"allow_partial_results": True}
381
+ })
382
+
383
+ # Generic alternative path for other failures
384
+ else:
385
+ for i, fix in enumerate(analysis.suggested_fixes[:3], 1):
386
+ path.append({
387
+ "step": i,
388
+ "action": "apply_fix",
389
+ "description": fix,
390
+ "params": {"fix": fix}
391
+ })
392
+
393
+ return path
394
+
395
+ def _predict_outcome(self, analysis: FailureAnalysis, alternative_path: List[Dict[str, Any]]) -> str:
396
+ """Predict the outcome of executing the alternative path."""
397
+ failure = analysis.failure
398
+
399
+ if failure.failure_type.value == "blocked_by_control_plane":
400
+ return "Action will be executed with proper authorization and safety checks"
401
+ elif failure.failure_type.value == "timeout":
402
+ return "Operation will complete within timeout with progress monitoring"
403
+ else:
404
+ return f"Failure {failure.failure_type.value} will be prevented by applying suggested fixes"
405
+
406
+ def _calculate_risk(self, analysis: FailureAnalysis, alternative_path: List[Dict[str, Any]]) -> float:
407
+ """Calculate risk score for the alternative path."""
408
+ risk = 0.3 # Base risk
409
+
410
+ # Lower risk if confidence is high
411
+ risk -= (analysis.confidence_score * 0.2)
412
+
413
+ # Lower risk if we have multiple steps (more thorough)
414
+ if len(alternative_path) >= 3:
415
+ risk -= 0.1
416
+
417
+ # Higher risk for unknown failure types
418
+ if analysis.failure.failure_type.value == "unknown":
419
+ risk += 0.2
420
+
421
+ return max(0.0, min(1.0, risk))
422
+
423
+ def _estimate_success_rate(self, analysis: FailureAnalysis, risk_score: float) -> float:
424
+ """Estimate success rate of the alternative path."""
425
+ # Base success rate from confidence
426
+ success_rate = analysis.confidence_score
427
+
428
+ # Adjust based on risk
429
+ success_rate = success_rate * (1.0 - risk_score * 0.5)
430
+
431
+ # Bonus for having similar failures (we've seen this before)
432
+ if len(analysis.similar_failures) > 0:
433
+ success_rate += 0.1
434
+
435
+ return max(0.0, min(1.0, success_rate))
436
+
437
+ def get_best_simulation(self, simulations: List[SimulationResult]) -> SimulationResult:
438
+ """Get the best simulation from a list based on success rate and risk."""
439
+ if not simulations:
440
+ raise ValueError("No simulations provided")
441
+
442
+ # Sort by estimated success rate (desc) and risk score (asc)
443
+ sorted_sims = sorted(
444
+ simulations,
445
+ key=lambda s: (s.estimated_success_rate, -s.risk_score),
446
+ reverse=True
447
+ )
448
+
449
+ return sorted_sims[0]
@@ -0,0 +1,85 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+
4
+ """
5
+ Teacher - Simplified reference implementation for the Shadow Teacher.
6
+
7
+ This is a reference implementation showing the core concept of using a
8
+ "Teacher Model" (stronger reasoning model) to diagnose why an agent failed.
9
+
10
+ The production implementation is integrated throughout the analyzer.py and
11
+ completeness_auditor.py modules with full trace capture and cognitive diagnosis.
12
+ """
13
+
14
+
15
+ def _sanitize_input(text: str, max_length: int = 1000) -> str:
16
+ """
17
+ Sanitize input to prevent prompt injection.
18
+
19
+ Args:
20
+ text: Input text to sanitize
21
+ max_length: Maximum allowed length
22
+
23
+ Returns:
24
+ Sanitized text
25
+ """
26
+ if not text:
27
+ return ""
28
+
29
+ # Truncate to max length
30
+ text = str(text)[:max_length]
31
+
32
+ # Remove potential prompt injection patterns
33
+ # In production, use more sophisticated sanitization
34
+ dangerous_patterns = ["ignore previous", "ignore all", "disregard", "new instructions"]
35
+ text_lower = text.lower()
36
+ for pattern in dangerous_patterns:
37
+ if pattern in text_lower:
38
+ text = text.replace(pattern, "[FILTERED]")
39
+
40
+ return text
41
+
42
+
43
+ async def diagnose_failure(prompt, failed_response, tool_trace):
44
+ """
45
+ Uses a 'Reasoning Model' (e.g., o1 or Claude 3.5 Sonnet)
46
+ to find the Root Cause.
47
+
48
+ Args:
49
+ prompt: The original task/prompt that failed
50
+ failed_response: The agent's failed response
51
+ tool_trace: Trace of tools/actions the agent attempted
52
+
53
+ Returns:
54
+ dict: Diagnosis with cause and lesson_patch
55
+ """
56
+ # Sanitize inputs to prevent prompt injection
57
+ safe_prompt = _sanitize_input(prompt)
58
+ safe_response = _sanitize_input(failed_response)
59
+ safe_trace = _sanitize_input(tool_trace)
60
+
61
+ teacher_prompt = f"""
62
+ The Agent failed to complete this task: '{safe_prompt}'.
63
+
64
+ Agent Output: {safe_response}
65
+ Tool Trace: {safe_trace}
66
+
67
+ Task:
68
+ 1. Did the agent try hard enough? (Laziness)
69
+ 2. Did the agent hallucinate a tool parameter? (Skill Issue)
70
+ 3. Write a 1-sentence 'Lesson' that fixes this specific error.
71
+
72
+ Output Format: JSON {{ "cause": "...", "lesson_patch": "..." }}
73
+ """
74
+
75
+ # In production, this would call the "Expensive" Model only on failure
76
+ # For this reference implementation, we simulate the response
77
+ # diagnosis = await llm_client.generate(model="o1-preview", prompt=teacher_prompt)
78
+
79
+ # Simulated diagnosis for reference
80
+ diagnosis = {
81
+ "cause": "Agent gave up without exhaustive search",
82
+ "lesson_patch": "Before reporting 'not found', check all data sources including archived partitions"
83
+ }
84
+
85
+ return diagnosis
agent_kernel/triage.py ADDED
@@ -0,0 +1,152 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+
4
+ """
5
+ Failure Triage Engine - Decides sync (JIT) vs async (batch) correction strategy.
6
+
7
+ This is the missing component that sits between Failure Detection and Correction.
8
+ It analyzes the context to determine if a failure should be fixed immediately
9
+ (blocking the user) or asynchronously (returning error quickly, fixing later).
10
+ """
11
+
12
+ from enum import Enum
13
+ from typing import Dict, Any, Optional
14
+
15
+
16
+ class FixStrategy(Enum):
17
+ """Strategy for fixing agent failures."""
18
+ SYNC_JIT = "jit_retry" # High Latency, High Reliability - Fix NOW and wait
19
+ ASYNC_BATCH = "async_patch" # Low Latency, Eventual Consistency - Fix LATER
20
+
21
+
22
+ class FailureTriage:
23
+ """
24
+ Decision engine for routing failures to sync (JIT) or async (batch) correction.
25
+
26
+ The triage engine applies three rules to determine criticality:
27
+ 1. Safety/Write Operations → SYNC_JIT (must fix immediately)
28
+ 2. High Effort Prompts → SYNC_JIT (user expects deep thinking)
29
+ 3. Read/Query Operations → ASYNC_BATCH (save user time)
30
+
31
+ This enables "thinking fast" (async) for trivial failures and
32
+ "thinking slow" (sync) for critical failures.
33
+ """
34
+
35
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
36
+ """
37
+ Initialize the triage engine.
38
+
39
+ Args:
40
+ config: Optional configuration for custom critical tools and keywords
41
+ """
42
+ self.config = config or {}
43
+
44
+ # Critical tools that require synchronous fixing (can be customized via config)
45
+ self.critical_tools = self.config.get("critical_tools", [
46
+ "delete_resource",
47
+ "update_db",
48
+ "execute_payment",
49
+ "drop_table",
50
+ "refund_user",
51
+ "delete_file",
52
+ "execute_sql",
53
+ "write_file",
54
+ "modify_permissions",
55
+ "delete_user" # User deletion is critical
56
+ ])
57
+
58
+ # Keywords indicating high-effort prompts requiring deep thinking
59
+ self.high_effort_keywords = self.config.get("high_effort_keywords", [
60
+ "carefully",
61
+ "critical",
62
+ "important",
63
+ "urgent",
64
+ "must",
65
+ "required",
66
+ "ensure"
67
+ ])
68
+
69
+ def decide_strategy(
70
+ self,
71
+ prompt: str,
72
+ tool_name: Optional[str] = None,
73
+ user_metadata: Optional[Dict[str, Any]] = None,
74
+ context: Optional[Dict[str, Any]] = None
75
+ ) -> FixStrategy:
76
+ """
77
+ Decide whether to fix this failure sync (JIT) or async (batch).
78
+
79
+ Decision Rules (in priority order):
80
+ 1. Cognitive failures with full trace → SYNC_JIT (deep diagnosis needed)
81
+ 2. Safety/Write Operations → SYNC_JIT
82
+ 3. High Effort Prompts → SYNC_JIT
83
+ 4. VIP Users → SYNC_JIT
84
+ 5. Default (Read/Query) → ASYNC_BATCH
85
+
86
+ Args:
87
+ prompt: The user prompt that led to the failure
88
+ tool_name: Name of the tool that failed (if available)
89
+ user_metadata: Metadata about the user (e.g., VIP status)
90
+ context: Additional context about the failure
91
+
92
+ Returns:
93
+ FixStrategy indicating sync (JIT) or async (batch) correction
94
+ """
95
+ # Rule 0: Cognitive failures with full trace (chain_of_thought + failed_action)
96
+ # These warrant immediate deep analysis with Shadow Teacher
97
+ if context:
98
+ has_chain = context.get("chain_of_thought") is not None
99
+ has_failed_action = context.get("failed_action") is not None
100
+ if has_chain and has_failed_action:
101
+ return FixStrategy.SYNC_JIT
102
+
103
+ # Rule 1: Safety/Write Operations are always Critical
104
+ if tool_name and tool_name in self.critical_tools:
105
+ return FixStrategy.SYNC_JIT
106
+
107
+ # Check context for critical actions (fallback if tool_name not provided)
108
+ if context:
109
+ action = context.get("action", "")
110
+ if action in self.critical_tools:
111
+ return FixStrategy.SYNC_JIT
112
+
113
+ # Also check failed_action if present
114
+ failed_action = context.get("failed_action")
115
+ if failed_action and isinstance(failed_action, dict):
116
+ failed_action_name = failed_action.get("action", "")
117
+ if failed_action_name in self.critical_tools:
118
+ return FixStrategy.SYNC_JIT
119
+
120
+ # Rule 2: "High Effort" prompts request deep thinking
121
+ prompt_lower = prompt.lower()
122
+ if any(keyword in prompt_lower for keyword in self.high_effort_keywords):
123
+ return FixStrategy.SYNC_JIT
124
+
125
+ # Rule 3: VIP users get priority treatment (optional)
126
+ if user_metadata and user_metadata.get("is_vip", False):
127
+ return FixStrategy.SYNC_JIT
128
+
129
+ # Rule 4: Default to Async for "Read/Query" failures to save user time
130
+ return FixStrategy.ASYNC_BATCH
131
+
132
+ def is_critical(
133
+ self,
134
+ prompt: str,
135
+ tool_name: Optional[str] = None,
136
+ user_metadata: Optional[Dict[str, Any]] = None,
137
+ context: Optional[Dict[str, Any]] = None
138
+ ) -> bool:
139
+ """
140
+ Convenience method to check if a failure is critical (needs SYNC_JIT).
141
+
142
+ Args:
143
+ prompt: The user prompt
144
+ tool_name: Name of the tool that failed
145
+ user_metadata: User metadata
146
+ context: Additional context
147
+
148
+ Returns:
149
+ True if critical (SYNC_JIT), False if non-critical (ASYNC_BATCH)
150
+ """
151
+ strategy = self.decide_strategy(prompt, tool_name, user_metadata, context)
152
+ return strategy == FixStrategy.SYNC_JIT