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,502 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Graph Debugger - Visual Trace Generator for Mute Agent
5
+
6
+ Generates visual artifacts showing:
7
+ - Green Path: Nodes traversed successfully
8
+ - Red Node: The exact node where constraint failed
9
+ - Grey Nodes: Unreachable parts of the graph
10
+
11
+ This proves "Deterministic Safety" - showing where the agent physically
12
+ could not reach certain nodes because the path was severed.
13
+ """
14
+
15
+ from dataclasses import dataclass, field
16
+ from typing import Dict, List, Optional, Set, Any
17
+ from enum import Enum
18
+ from datetime import datetime
19
+ import logging
20
+ import os
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ try:
25
+ import networkx as nx
26
+ NETWORKX_AVAILABLE = True
27
+ except ImportError:
28
+ NETWORKX_AVAILABLE = False
29
+
30
+ try:
31
+ from pyvis.network import Network
32
+ PYVIS_AVAILABLE = True
33
+ except ImportError:
34
+ PYVIS_AVAILABLE = False
35
+
36
+ try:
37
+ import matplotlib.pyplot as plt
38
+ import matplotlib.patches as mpatches
39
+ MATPLOTLIB_AVAILABLE = True
40
+ except ImportError:
41
+ MATPLOTLIB_AVAILABLE = False
42
+
43
+ VISUALIZATION_AVAILABLE = NETWORKX_AVAILABLE and (PYVIS_AVAILABLE or MATPLOTLIB_AVAILABLE)
44
+
45
+
46
+ class NodeState(Enum):
47
+ """States a node can be in during execution."""
48
+ SUCCESS = "success" # Green - traversed successfully
49
+ FAILURE = "failure" # Red - constraint failed here
50
+ UNREACHABLE = "unreachable" # Grey - could not be reached
51
+ PENDING = "pending" # Not yet visited
52
+
53
+
54
+ @dataclass
55
+ class ExecutionTrace:
56
+ """Tracks execution path through the knowledge graph."""
57
+ session_id: str
58
+ action_id: str
59
+ traversed_nodes: List[str] = field(default_factory=list)
60
+ failed_node: Optional[str] = None
61
+ node_states: Dict[str, NodeState] = field(default_factory=dict)
62
+ edge_traversals: List[tuple] = field(default_factory=list)
63
+ validation_errors: List[str] = field(default_factory=list)
64
+ timestamp: datetime = field(default_factory=datetime.now)
65
+ metadata: Dict[str, Any] = field(default_factory=dict)
66
+
67
+
68
+ class GraphDebugger:
69
+ """
70
+ The Graph Debugger generates visual artifacts for every execution.
71
+ Shows deterministic safety by visualizing which paths were accessible.
72
+ """
73
+
74
+ def __init__(self, knowledge_graph=None):
75
+ """
76
+ Initialize the Graph Debugger.
77
+
78
+ Args:
79
+ knowledge_graph: The MultidimensionalKnowledgeGraph to visualize
80
+ """
81
+ self.knowledge_graph = knowledge_graph
82
+ self.traces: List[ExecutionTrace] = []
83
+
84
+ if not VISUALIZATION_AVAILABLE:
85
+ missing = []
86
+ if not NETWORKX_AVAILABLE:
87
+ missing.append("networkx")
88
+ if not PYVIS_AVAILABLE:
89
+ missing.append("pyvis")
90
+ if not MATPLOTLIB_AVAILABLE:
91
+ missing.append("matplotlib")
92
+ print(f"Warning: Visualization libraries not available: {', '.join(missing)}")
93
+ print("Install with: pip install matplotlib networkx pyvis")
94
+
95
+ def create_trace(
96
+ self,
97
+ session_id: str,
98
+ action_id: str,
99
+ metadata: Optional[Dict[str, Any]] = None
100
+ ) -> ExecutionTrace:
101
+ """Create a new execution trace."""
102
+ trace = ExecutionTrace(
103
+ session_id=session_id,
104
+ action_id=action_id,
105
+ metadata=metadata or {}
106
+ )
107
+ self.traces.append(trace)
108
+ return trace
109
+
110
+ def record_node_visit(self, trace: ExecutionTrace, node_id: str, success: bool):
111
+ """Record a node visit in the trace."""
112
+ trace.traversed_nodes.append(node_id)
113
+ if success:
114
+ trace.node_states[node_id] = NodeState.SUCCESS
115
+ else:
116
+ trace.node_states[node_id] = NodeState.FAILURE
117
+ trace.failed_node = node_id
118
+
119
+ def record_edge_traversal(self, trace: ExecutionTrace, source_id: str, target_id: str):
120
+ """Record an edge traversal."""
121
+ trace.edge_traversals.append((source_id, target_id))
122
+
123
+ def mark_unreachable_nodes(self, trace: ExecutionTrace, all_node_ids: List[str]):
124
+ """Mark nodes that were not reached as unreachable."""
125
+ reached = set(trace.traversed_nodes)
126
+ for node_id in all_node_ids:
127
+ if node_id not in reached and node_id not in trace.node_states:
128
+ trace.node_states[node_id] = NodeState.UNREACHABLE
129
+
130
+ def visualize_trace(
131
+ self,
132
+ trace: ExecutionTrace,
133
+ output_path: str = "execution_trace.html",
134
+ format: str = "html"
135
+ ) -> str:
136
+ """
137
+ Generate a visual artifact for the execution trace.
138
+
139
+ Args:
140
+ trace: The execution trace to visualize
141
+ output_path: Where to save the visualization
142
+ format: 'html' (interactive) or 'png' (static image)
143
+
144
+ Returns:
145
+ Path to the generated visualization
146
+ """
147
+ if not VISUALIZATION_AVAILABLE:
148
+ print("Cannot generate visualization: libraries not installed")
149
+ return ""
150
+
151
+ if format == "html":
152
+ return self._generate_interactive_html(trace, output_path)
153
+ elif format == "png":
154
+ return self._generate_static_png(trace, output_path)
155
+ else:
156
+ raise ValueError(f"Unsupported format: {format}")
157
+
158
+ def _generate_interactive_html(self, trace: ExecutionTrace, output_path: str) -> str:
159
+ """Generate an interactive HTML visualization using pyvis."""
160
+ # Create a directed graph
161
+ net = Network(
162
+ height="750px",
163
+ width="100%",
164
+ directed=True,
165
+ notebook=False,
166
+ bgcolor="#ffffff",
167
+ font_color="#000000"
168
+ )
169
+
170
+ # Configure physics for better layout
171
+ net.set_options("""
172
+ {
173
+ "physics": {
174
+ "enabled": true,
175
+ "barnesHut": {
176
+ "gravitationalConstant": -8000,
177
+ "centralGravity": 0.3,
178
+ "springLength": 150,
179
+ "springConstant": 0.04
180
+ }
181
+ },
182
+ "nodes": {
183
+ "font": {
184
+ "size": 16,
185
+ "face": "arial"
186
+ }
187
+ },
188
+ "edges": {
189
+ "arrows": {
190
+ "to": {
191
+ "enabled": true,
192
+ "scaleFactor": 0.5
193
+ }
194
+ },
195
+ "smooth": {
196
+ "type": "continuous"
197
+ }
198
+ }
199
+ }
200
+ """)
201
+
202
+ # Add nodes with colors based on state
203
+ for node_id, state in trace.node_states.items():
204
+ color, title = self._get_node_style(node_id, state, trace)
205
+
206
+ # Make failed node stand out
207
+ if state == NodeState.FAILURE:
208
+ net.add_node(
209
+ node_id,
210
+ label=node_id,
211
+ color=color,
212
+ title=title,
213
+ size=30,
214
+ borderWidth=3,
215
+ borderWidthSelected=4
216
+ )
217
+ else:
218
+ net.add_node(
219
+ node_id,
220
+ label=node_id,
221
+ color=color,
222
+ title=title,
223
+ size=20
224
+ )
225
+
226
+ # Add edges from knowledge graph if available
227
+ if self.knowledge_graph:
228
+ self._add_edges_from_knowledge_graph(net, trace)
229
+ else:
230
+ # Add edges from trace
231
+ for source, target in trace.edge_traversals:
232
+ # Check if edge was part of success or failure path
233
+ edge_color = "#2ecc71" if source in trace.traversed_nodes else "#95a5a6"
234
+ net.add_edge(source, target, color=edge_color, width=2)
235
+
236
+ # Add legend as HTML title
237
+ html_legend = self._create_html_legend(trace)
238
+
239
+ # Generate the HTML
240
+ net.save_graph(output_path)
241
+
242
+ # Insert legend into HTML
243
+ self._inject_legend_into_html(output_path, html_legend)
244
+
245
+ print(f"Interactive visualization saved to: {output_path}")
246
+ return output_path
247
+
248
+ def _generate_static_png(self, trace: ExecutionTrace, output_path: str) -> str:
249
+ """Generate a static PNG visualization using matplotlib and networkx."""
250
+ # Create a directed graph
251
+ G = nx.DiGraph()
252
+
253
+ # Add nodes
254
+ for node_id in trace.node_states.keys():
255
+ G.add_node(node_id)
256
+
257
+ # Add edges
258
+ if self.knowledge_graph:
259
+ # Extract edges from knowledge graph
260
+ for dim_name, subgraph in self.knowledge_graph.subgraphs.items():
261
+ for edge in subgraph.edges:
262
+ if edge.source_id in G.nodes and edge.target_id in G.nodes:
263
+ G.add_edge(edge.source_id, edge.target_id)
264
+ else:
265
+ for source, target in trace.edge_traversals:
266
+ G.add_edge(source, target)
267
+
268
+ # Create figure
269
+ plt.figure(figsize=(14, 10))
270
+
271
+ # Use hierarchical layout
272
+ try:
273
+ pos = nx.spring_layout(G, k=2, iterations=50)
274
+ except (ValueError, RuntimeError) as e:
275
+ logger.debug("spring_layout failed, falling back to shell_layout: %s", e)
276
+ pos = nx.shell_layout(G)
277
+
278
+ # Draw nodes with colors based on state
279
+ for state in NodeState:
280
+ nodes = [n for n, s in trace.node_states.items() if s == state]
281
+ if nodes:
282
+ color, label = self._get_node_color_for_png(state)
283
+ nx.draw_networkx_nodes(
284
+ G, pos,
285
+ nodelist=nodes,
286
+ node_color=color,
287
+ node_size=1000 if state == NodeState.FAILURE else 700,
288
+ label=label,
289
+ alpha=0.9
290
+ )
291
+
292
+ # Draw edges
293
+ nx.draw_networkx_edges(
294
+ G, pos,
295
+ edge_color='#95a5a6',
296
+ arrows=True,
297
+ arrowsize=20,
298
+ width=2,
299
+ alpha=0.6
300
+ )
301
+
302
+ # Highlight traversed edges
303
+ traversed_edges = [(s, t) for s, t in trace.edge_traversals if G.has_edge(s, t)]
304
+ if traversed_edges:
305
+ nx.draw_networkx_edges(
306
+ G, pos,
307
+ edgelist=traversed_edges,
308
+ edge_color='#2ecc71',
309
+ arrows=True,
310
+ arrowsize=20,
311
+ width=3,
312
+ alpha=0.9
313
+ )
314
+
315
+ # Draw labels
316
+ nx.draw_networkx_labels(G, pos, font_size=10, font_weight='bold')
317
+
318
+ # Add title and legend
319
+ plt.title(
320
+ f"Execution Trace: {trace.action_id}\n"
321
+ f"Session: {trace.session_id}",
322
+ fontsize=14,
323
+ fontweight='bold',
324
+ pad=20
325
+ )
326
+
327
+ plt.legend(loc='upper left', fontsize=10)
328
+ plt.axis('off')
329
+ plt.tight_layout()
330
+
331
+ # Save
332
+ plt.savefig(output_path, dpi=300, bbox_inches='tight', facecolor='white')
333
+ plt.close()
334
+
335
+ print(f"Static visualization saved to: {output_path}")
336
+ return output_path
337
+
338
+ def _get_node_style(self, node_id: str, state: NodeState, trace: ExecutionTrace) -> tuple:
339
+ """Get node color and title based on state."""
340
+ if state == NodeState.SUCCESS:
341
+ color = "#2ecc71" # Green
342
+ title = f"{node_id}\n✓ Traversed successfully"
343
+ elif state == NodeState.FAILURE:
344
+ color = "#e74c3c" # Red
345
+ errors = "\n".join(trace.validation_errors) if trace.validation_errors else "Constraint failed"
346
+ title = f"{node_id}\n✗ FAILED\n{errors}"
347
+ elif state == NodeState.UNREACHABLE:
348
+ color = "#95a5a6" # Grey
349
+ title = f"{node_id}\n○ Unreachable (path severed)"
350
+ else:
351
+ color = "#3498db" # Blue
352
+ title = f"{node_id}\n○ Pending"
353
+
354
+ return color, title
355
+
356
+ def _get_node_color_for_png(self, state: NodeState) -> tuple:
357
+ """Get node color and label for PNG visualization."""
358
+ if state == NodeState.SUCCESS:
359
+ return "#2ecc71", "Success (Traversed)"
360
+ elif state == NodeState.FAILURE:
361
+ return "#e74c3c", "Failure (Constraint Violated)"
362
+ elif state == NodeState.UNREACHABLE:
363
+ return "#95a5a6", "Unreachable (Path Severed)"
364
+ else:
365
+ return "#3498db", "Pending"
366
+
367
+ def _add_edges_from_knowledge_graph(self, net, trace: ExecutionTrace):
368
+ """Add edges from the knowledge graph to the visualization."""
369
+ if not self.knowledge_graph:
370
+ return
371
+
372
+ traversed = set(trace.traversed_nodes)
373
+
374
+ for dim_name, subgraph in self.knowledge_graph.subgraphs.items():
375
+ for edge in subgraph.edges:
376
+ # Only add edges between nodes that are in the trace
377
+ if edge.source_id in trace.node_states and edge.target_id in trace.node_states:
378
+ # Color based on whether edge was traversed
379
+ if edge.source_id in traversed:
380
+ color = "#2ecc71" # Green for traversed
381
+ width = 3
382
+ else:
383
+ color = "#95a5a6" # Grey for not traversed
384
+ width = 1
385
+
386
+ title = f"{edge.edge_type.value}: {edge.source_id} → {edge.target_id}"
387
+ net.add_edge(
388
+ edge.source_id,
389
+ edge.target_id,
390
+ color=color,
391
+ width=width,
392
+ title=title
393
+ )
394
+
395
+ def _create_html_legend(self, trace: ExecutionTrace) -> str:
396
+ """Create HTML legend for the visualization."""
397
+ success_count = sum(1 for s in trace.node_states.values() if s == NodeState.SUCCESS)
398
+ failure_count = sum(1 for s in trace.node_states.values() if s == NodeState.FAILURE)
399
+ unreachable_count = sum(1 for s in trace.node_states.values() if s == NodeState.UNREACHABLE)
400
+
401
+ legend = f"""
402
+ <div style="position: absolute; top: 10px; right: 10px; background: white;
403
+ padding: 15px; border: 2px solid #ccc; border-radius: 5px;
404
+ font-family: Arial; max-width: 300px;">
405
+ <h3 style="margin: 0 0 10px 0;">Execution Trace Legend</h3>
406
+ <p style="margin: 5px 0;"><span style="color: #2ecc71;">●</span> <strong>Green:</strong> Traversed successfully ({success_count})</p>
407
+ <p style="margin: 5px 0;"><span style="color: #e74c3c;">●</span> <strong>Red:</strong> Constraint failed ({failure_count})</p>
408
+ <p style="margin: 5px 0;"><span style="color: #95a5a6;">●</span> <strong>Grey:</strong> Unreachable ({unreachable_count})</p>
409
+ <hr style="margin: 10px 0;">
410
+ <p style="margin: 5px 0; font-size: 12px;"><strong>Session:</strong> {trace.session_id}</p>
411
+ <p style="margin: 5px 0; font-size: 12px;"><strong>Action:</strong> {trace.action_id}</p>
412
+ {f'<p style="margin: 5px 0; font-size: 12px; color: #e74c3c;"><strong>Failed at:</strong> {trace.failed_node}</p>' if trace.failed_node else ''}
413
+ </div>
414
+ """
415
+ return legend
416
+
417
+ def _inject_legend_into_html(self, html_path: str, legend_html: str):
418
+ """Inject legend HTML into the generated visualization."""
419
+ try:
420
+ with open(html_path, 'r') as f:
421
+ html_content = f.read()
422
+
423
+ # Insert legend before closing body tag
424
+ html_content = html_content.replace('</body>', f'{legend_html}</body>')
425
+
426
+ with open(html_path, 'w') as f:
427
+ f.write(html_content)
428
+ except FileNotFoundError:
429
+ print(f"Warning: Could not find HTML file: {html_path}")
430
+ except PermissionError:
431
+ print(f"Warning: Permission denied writing to: {html_path}")
432
+ except Exception as e:
433
+ print(f"Warning: Could not inject legend: {type(e).__name__}: {e}")
434
+
435
+ def generate_comparison_visualization(
436
+ self,
437
+ traces: List[ExecutionTrace],
438
+ output_path: str = "trace_comparison.png"
439
+ ) -> str:
440
+ """
441
+ Generate a side-by-side comparison of multiple traces.
442
+ Useful for showing how different contexts lead to different paths.
443
+ """
444
+ if not VISUALIZATION_AVAILABLE:
445
+ print("Cannot generate visualization: libraries not installed")
446
+ return ""
447
+
448
+ num_traces = len(traces)
449
+ fig, axes = plt.subplots(1, num_traces, figsize=(7 * num_traces, 6))
450
+
451
+ if num_traces == 1:
452
+ axes = [axes]
453
+
454
+ for idx, trace in enumerate(traces):
455
+ ax = axes[idx]
456
+
457
+ # Create graph for this trace
458
+ G = nx.DiGraph()
459
+ for node_id in trace.node_states.keys():
460
+ G.add_node(node_id)
461
+ for source, target in trace.edge_traversals:
462
+ G.add_edge(source, target)
463
+
464
+ # Layout
465
+ try:
466
+ pos = nx.spring_layout(G, k=1.5, iterations=50)
467
+ except (ValueError, RuntimeError) as e:
468
+ logger.debug("spring_layout failed, falling back to shell_layout: %s", e)
469
+ pos = nx.shell_layout(G)
470
+
471
+ # Draw nodes
472
+ for state in NodeState:
473
+ nodes = [n for n, s in trace.node_states.items() if s == state]
474
+ if nodes:
475
+ color, _ = self._get_node_color_for_png(state)
476
+ nx.draw_networkx_nodes(
477
+ G, pos,
478
+ nodelist=nodes,
479
+ node_color=color,
480
+ node_size=500,
481
+ alpha=0.9,
482
+ ax=ax
483
+ )
484
+
485
+ # Draw edges
486
+ nx.draw_networkx_edges(G, pos, edge_color='#95a5a6',
487
+ arrows=True, arrowsize=15, width=1.5,
488
+ alpha=0.6, ax=ax)
489
+
490
+ # Draw labels
491
+ nx.draw_networkx_labels(G, pos, font_size=8, font_weight='bold', ax=ax)
492
+
493
+ ax.set_title(f"Trace {idx + 1}: {trace.action_id}", fontweight='bold')
494
+ ax.axis('off')
495
+
496
+ plt.suptitle("Execution Trace Comparison", fontsize=16, fontweight='bold')
497
+ plt.tight_layout()
498
+ plt.savefig(output_path, dpi=300, bbox_inches='tight', facecolor='white')
499
+ plt.close()
500
+
501
+ print(f"Comparison visualization saved to: {output_path}")
502
+ return output_path
nexus/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Nexus Trust Exchange
2
+
3
+ **Agent Trust Exchange — viral registry and communication board for AI agents.**
4
+
5
+ > ⚠️ **RESEARCH PROTOTYPE** — This module is in pre-alpha. Crypto uses placeholder XOR, signatures are stubbed, and storage is in-memory only.
6
+
7
+ ## Overview
8
+
9
+ Nexus provides a decentralized trust exchange layer for AI agent ecosystems. It enables agents to:
10
+
11
+ - **Register** capabilities and identity on a shared registry
12
+ - **Exchange** trust attestations with other agents
13
+ - **Arbitrate** disputes through an escrow/arbiter system
14
+ - **Build reputation** via a weighted reputation graph
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install nexus-trust-exchange
20
+ ```
21
+
22
+ ## Components
23
+
24
+ | Module | Purpose |
25
+ |--------|---------|
26
+ | `registry.py` | Agent registration and capability discovery |
27
+ | `client.py` | Client SDK for interacting with the exchange |
28
+ | `arbiter.py` | Trust dispute resolution |
29
+ | `escrow.py` | Conditional trust escrow |
30
+ | `dmz.py` | Demilitarized zone for untrusted agent interaction |
31
+ | `reputation.py` | Reputation scoring and graph |
32
+ | `schemas/` | Pydantic models for all exchange messages |
33
+
34
+ ## Quick Start
35
+
36
+ ```python
37
+ from nexus import NexusRegistry, NexusClient
38
+
39
+ # Create a registry
40
+ registry = NexusRegistry()
41
+
42
+ # Register an agent
43
+ registry.register_agent(
44
+ agent_id="agent-001",
45
+ capabilities=["code-review", "testing"],
46
+ trust_level=0.8
47
+ )
48
+ ```
49
+
50
+ ## Part of Agent-OS
51
+
52
+ This module is part of the [Agent-OS](https://github.com/microsoft/agent-governance-toolkit) ecosystem. Install the full stack:
53
+
54
+ ```bash
55
+ pip install agent-os-kernel
56
+ ```
57
+
58
+ ## License
59
+
60
+ MIT
nexus/__init__.py ADDED
@@ -0,0 +1,51 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Nexus: The Agent Trust Exchange
5
+
6
+ A viral, cloud-based registry and communication board that uses the Agent OS
7
+ kernel to enforce trust. Serves as a neutral ground where agents can discover
8
+ each other, negotiate contracts via IATP, and settle rewards for successful tasks.
9
+
10
+ The "Visa Network" for AI Agents.
11
+ """
12
+
13
+ from .client import NexusClient
14
+ from .registry import AgentRegistry
15
+ from .reputation import ReputationEngine, TrustScore
16
+ from .escrow import ProofOfOutcome, EscrowManager
17
+ from .arbiter import Arbiter, DisputeResolution
18
+ from .dmz import DMZProtocol, DataHandlingPolicy
19
+ from .exceptions import (
20
+ NexusError,
21
+ IATPUnverifiedPeerException,
22
+ IATPInsufficientTrustException,
23
+ EscrowError,
24
+ DisputeError,
25
+ )
26
+
27
+ __version__ = "3.1.0"
28
+ __all__ = [
29
+ # Client
30
+ "NexusClient",
31
+ # Registry
32
+ "AgentRegistry",
33
+ # Reputation
34
+ "ReputationEngine",
35
+ "TrustScore",
36
+ # Escrow
37
+ "ProofOfOutcome",
38
+ "EscrowManager",
39
+ # Arbiter
40
+ "Arbiter",
41
+ "DisputeResolution",
42
+ # DMZ
43
+ "DMZProtocol",
44
+ "DataHandlingPolicy",
45
+ # Exceptions
46
+ "NexusError",
47
+ "IATPUnverifiedPeerException",
48
+ "IATPInsufficientTrustException",
49
+ "EscrowError",
50
+ "DisputeError",
51
+ ]