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
atr/registry.py ADDED
@@ -0,0 +1,452 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Registry for storing and retrieving tool specifications.
5
+
6
+ The registry is a lightweight lookup mechanism that stores tool specs
7
+ but does NOT execute them. Execution is the responsibility of the
8
+ Agent Runtime (Control Plane).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ import warnings
15
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
16
+
17
+ from .schema import CostLevel, SideEffect, ToolHandle, ToolSpec
18
+
19
+ if TYPE_CHECKING:
20
+ pass
21
+
22
+
23
+ class RegistryError(Exception):
24
+ """Base exception for registry errors."""
25
+
26
+ pass
27
+
28
+
29
+ class ToolNotFoundError(RegistryError):
30
+ """Raised when a tool is not found in the registry."""
31
+
32
+ pass
33
+
34
+
35
+ class ToolAlreadyExistsError(RegistryError):
36
+ """Raised when attempting to register a tool that already exists."""
37
+
38
+ pass
39
+
40
+
41
+ class VersionConstraintError(RegistryError):
42
+ """Raised when no tool version matches the constraint."""
43
+
44
+ pass
45
+
46
+
47
+ def parse_version(version: str) -> Tuple[int, int, int]:
48
+ """Parse a semantic version string into a tuple.
49
+
50
+ Args:
51
+ version: Version string (e.g., "1.2.3").
52
+
53
+ Returns:
54
+ Tuple of (major, minor, patch).
55
+ """
56
+ match = re.match(r"^(\d+)\.(\d+)\.(\d+)", version)
57
+ if match:
58
+ return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
59
+ return (0, 0, 0)
60
+
61
+
62
+ def version_matches(version: str, constraint: str) -> bool:
63
+ """Check if a version matches a constraint.
64
+
65
+ Supports constraints like:
66
+ - "1.0.0" - exact match
67
+ - ">=1.0.0" - greater than or equal
68
+ - ">1.0.0" - greater than
69
+ - "<=1.0.0" - less than or equal
70
+ - "<1.0.0" - less than
71
+ - "^1.0.0" - compatible with (same major version)
72
+ - "~1.0.0" - approximately (same major.minor)
73
+ - "*" - any version
74
+
75
+ Args:
76
+ version: The version to check.
77
+ constraint: The version constraint.
78
+
79
+ Returns:
80
+ True if version matches constraint.
81
+ """
82
+ if constraint == "*" or constraint == "":
83
+ return True
84
+
85
+ v = parse_version(version)
86
+
87
+ # Handle comparison operators
88
+ if constraint.startswith(">="):
89
+ c = parse_version(constraint[2:])
90
+ return v >= c
91
+ elif constraint.startswith("<="):
92
+ c = parse_version(constraint[2:])
93
+ return v <= c
94
+ elif constraint.startswith(">"):
95
+ c = parse_version(constraint[1:])
96
+ return v > c
97
+ elif constraint.startswith("<"):
98
+ c = parse_version(constraint[1:])
99
+ return v < c
100
+ elif constraint.startswith("^"):
101
+ # Caret: compatible with major version
102
+ c = parse_version(constraint[1:])
103
+ return v[0] == c[0] and v >= c
104
+ elif constraint.startswith("~"):
105
+ # Tilde: compatible with major.minor
106
+ c = parse_version(constraint[1:])
107
+ return v[0] == c[0] and v[1] == c[1] and v >= c
108
+ else:
109
+ # Exact match
110
+ c = parse_version(constraint)
111
+ return v == c
112
+
113
+
114
+ class Registry:
115
+ """Lightweight tool registry using a local dictionary store.
116
+
117
+ This registry stores tool specifications and their callables but does NOT
118
+ execute them. It's purely a lookup and discovery mechanism.
119
+
120
+ The actual execution is handled by the Agent Runtime (Control Plane).
121
+
122
+ Supports versioning: multiple versions of the same tool can be registered.
123
+ """
124
+
125
+ def __init__(
126
+ self,
127
+ container: Optional[Any] = None, # DependencyContainer
128
+ metrics_collector: Optional[Any] = None, # MetricsCollector
129
+ access_manager: Optional[Any] = None, # AccessControlManager
130
+ ):
131
+ """Initialize an empty registry.
132
+
133
+ Args:
134
+ container: Optional dependency container for injection.
135
+ metrics_collector: Optional metrics collector.
136
+ access_manager: Optional access control manager.
137
+ """
138
+ # Key: tool_name, Value: dict of version -> ToolSpec
139
+ self._tools: Dict[str, Dict[str, ToolSpec]] = {}
140
+ self._container = container
141
+ self._metrics = metrics_collector
142
+ self._access_manager = access_manager
143
+
144
+ def register_tool(
145
+ self, spec: ToolSpec, callable_func: Optional[Callable] = None, replace: bool = False
146
+ ) -> None:
147
+ """Register a tool in the registry.
148
+
149
+ Args:
150
+ spec: The tool specification
151
+ callable_func: The actual callable function (stored but not executed)
152
+ replace: Whether to replace if tool version already exists
153
+
154
+ Raises:
155
+ ToolAlreadyExistsError: If tool version exists and replace=False
156
+ """
157
+ tool_name = spec.metadata.name
158
+ tool_version = spec.metadata.version
159
+
160
+ # Initialize version dict if needed
161
+ if tool_name not in self._tools:
162
+ self._tools[tool_name] = {}
163
+
164
+ if tool_version in self._tools[tool_name] and not replace:
165
+ raise ToolAlreadyExistsError(
166
+ f"Tool '{tool_name}' version '{tool_version}' already exists. "
167
+ "Use replace=True to overwrite."
168
+ )
169
+
170
+ # Store the callable but NEVER execute it
171
+ if callable_func is not None:
172
+ spec._callable_func = callable_func
173
+
174
+ self._tools[tool_name][tool_version] = spec
175
+
176
+ def get_tool(
177
+ self, name: str, version: Optional[str] = None, include_deprecated: bool = False
178
+ ) -> ToolSpec:
179
+ """Retrieve a tool specification by name and optional version constraint.
180
+
181
+ Args:
182
+ name: The tool name
183
+ version: Version constraint (e.g., ">=1.0.0", "^1.0.0", "1.2.3")
184
+ If None, returns the latest version.
185
+ include_deprecated: Whether to include deprecated versions
186
+
187
+ Returns:
188
+ The tool specification (includes the callable but doesn't execute it)
189
+
190
+ Raises:
191
+ ToolNotFoundError: If tool is not found
192
+ VersionConstraintError: If no version matches constraint
193
+ """
194
+ if name not in self._tools:
195
+ raise ToolNotFoundError(f"Tool '{name}' not found in registry")
196
+
197
+ versions = self._tools[name]
198
+
199
+ if not versions:
200
+ raise ToolNotFoundError(f"Tool '{name}' has no registered versions")
201
+
202
+ # Filter out deprecated if needed
203
+ available = {
204
+ v: spec
205
+ for v, spec in versions.items()
206
+ if include_deprecated or not spec.metadata.deprecated
207
+ }
208
+
209
+ if not available:
210
+ raise ToolNotFoundError(
211
+ f"Tool '{name}' has no non-deprecated versions. "
212
+ "Use include_deprecated=True to access deprecated versions."
213
+ )
214
+
215
+ if version is None:
216
+ # Return latest version
217
+ latest_version = max(available.keys(), key=parse_version)
218
+ return available[latest_version]
219
+
220
+ # Find matching versions
221
+ matching = [(v, spec) for v, spec in available.items() if version_matches(v, version)]
222
+
223
+ if not matching:
224
+ raise VersionConstraintError(
225
+ f"No version of '{name}' matches constraint '{version}'. "
226
+ f"Available versions: {list(available.keys())}"
227
+ )
228
+
229
+ # Return the highest matching version
230
+ best_version = max(matching, key=lambda x: parse_version(x[0]))
231
+ return best_version[1]
232
+
233
+ def get_tool_handle(
234
+ self, name: str, version: Optional[str] = None, include_deprecated: bool = False
235
+ ) -> ToolHandle:
236
+ """Get a ToolHandle for executing a tool with all policies applied.
237
+
238
+ Args:
239
+ name: The tool name
240
+ version: Version constraint
241
+ include_deprecated: Whether to include deprecated versions
242
+
243
+ Returns:
244
+ ToolHandle ready for execution
245
+ """
246
+ spec = self.get_tool(name, version, include_deprecated)
247
+
248
+ # Warn if deprecated
249
+ if spec.metadata.deprecated:
250
+ msg = f"Tool '{name}' version '{spec.version}' is deprecated."
251
+ if spec.metadata.deprecated_message:
252
+ msg += f" {spec.metadata.deprecated_message}"
253
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
254
+
255
+ return ToolHandle(
256
+ spec=spec,
257
+ container=self._container,
258
+ metrics_collector=self._metrics,
259
+ access_manager=self._access_manager,
260
+ )
261
+
262
+ def get_all_versions(self, name: str) -> List[str]:
263
+ """Get all registered versions of a tool.
264
+
265
+ Args:
266
+ name: The tool name
267
+
268
+ Returns:
269
+ List of version strings, sorted newest first
270
+
271
+ Raises:
272
+ ToolNotFoundError: If tool is not found
273
+ """
274
+ if name not in self._tools:
275
+ raise ToolNotFoundError(f"Tool '{name}' not found in registry")
276
+
277
+ versions = list(self._tools[name].keys())
278
+ return sorted(versions, key=parse_version, reverse=True)
279
+
280
+ def get_callable(self, name: str, version: Optional[str] = None) -> Callable:
281
+ """Get the callable function for a tool.
282
+
283
+ This returns the function object but does NOT execute it.
284
+ The caller (Agent Runtime) is responsible for execution.
285
+
286
+ Args:
287
+ name: The tool name
288
+ version: Optional version constraint
289
+
290
+ Returns:
291
+ The callable function object
292
+
293
+ Raises:
294
+ ToolNotFoundError: If tool is not found
295
+ ValueError: If tool has no callable
296
+ """
297
+ tool = self.get_tool(name, version)
298
+
299
+ if tool._callable_func is None:
300
+ raise ValueError(f"Tool '{name}' has no callable function")
301
+
302
+ return tool._callable_func
303
+
304
+ def list_tools(
305
+ self,
306
+ tag: Optional[str] = None,
307
+ cost: Optional[CostLevel] = None,
308
+ side_effect: Optional[SideEffect] = None,
309
+ include_all_versions: bool = False,
310
+ include_deprecated: bool = False,
311
+ ) -> List[ToolSpec]:
312
+ """List all registered tools with optional filtering.
313
+
314
+ Args:
315
+ tag: Filter by tag
316
+ cost: Filter by cost level
317
+ side_effect: Filter by side effect
318
+ include_all_versions: If True, return all versions. If False, only latest.
319
+ include_deprecated: Whether to include deprecated tools
320
+
321
+ Returns:
322
+ List of matching tool specifications
323
+ """
324
+ tools: List[ToolSpec] = []
325
+
326
+ for _name, versions in self._tools.items():
327
+ if include_all_versions:
328
+ specs = list(versions.values())
329
+ else:
330
+ # Get latest version
331
+ if versions:
332
+ latest_version = max(versions.keys(), key=parse_version)
333
+ specs = [versions[latest_version]]
334
+ else:
335
+ specs = []
336
+
337
+ for spec in specs:
338
+ # Filter deprecated
339
+ if not include_deprecated and spec.metadata.deprecated:
340
+ continue
341
+
342
+ # Apply filters
343
+ if tag is not None and tag not in spec.metadata.tags:
344
+ continue
345
+ if cost is not None and spec.metadata.cost != cost:
346
+ continue
347
+ if side_effect is not None and side_effect not in spec.metadata.side_effects:
348
+ continue
349
+
350
+ tools.append(spec)
351
+
352
+ return tools
353
+
354
+ def search_tools(self, query: str, include_all_versions: bool = False) -> List[ToolSpec]:
355
+ """Search tools by name, description, or tags.
356
+
357
+ Args:
358
+ query: Search query string
359
+ include_all_versions: Whether to search all versions
360
+
361
+ Returns:
362
+ List of matching tool specifications
363
+ """
364
+ query_lower = query.lower()
365
+ results = []
366
+
367
+ for _name, versions in self._tools.items():
368
+ if include_all_versions:
369
+ specs = list(versions.values())
370
+ else:
371
+ if versions:
372
+ latest_version = max(versions.keys(), key=parse_version)
373
+ specs = [versions[latest_version]]
374
+ else:
375
+ specs = []
376
+
377
+ for tool in specs:
378
+ # Check name
379
+ if query_lower in tool.metadata.name.lower():
380
+ results.append(tool)
381
+ continue
382
+
383
+ # Check description
384
+ if query_lower in tool.metadata.description.lower():
385
+ results.append(tool)
386
+ continue
387
+
388
+ # Check tags
389
+ if any(query_lower in tag.lower() for tag in tool.metadata.tags):
390
+ results.append(tool)
391
+ continue
392
+
393
+ return results
394
+
395
+ def unregister_tool(self, name: str, version: Optional[str] = None) -> None:
396
+ """Remove a tool from the registry.
397
+
398
+ Args:
399
+ name: The tool name
400
+ version: Specific version to remove, or None to remove all versions
401
+
402
+ Raises:
403
+ ToolNotFoundError: If tool is not found
404
+ """
405
+ if name not in self._tools:
406
+ raise ToolNotFoundError(f"Tool '{name}' not found in registry")
407
+
408
+ if version is None:
409
+ # Remove all versions
410
+ del self._tools[name]
411
+ else:
412
+ if version not in self._tools[name]:
413
+ raise ToolNotFoundError(f"Tool '{name}' version '{version}' not found in registry")
414
+ del self._tools[name][version]
415
+
416
+ # Clean up if no versions left
417
+ if not self._tools[name]:
418
+ del self._tools[name]
419
+
420
+ def deprecate_tool(self, name: str, version: str, message: Optional[str] = None) -> None:
421
+ """Mark a tool version as deprecated.
422
+
423
+ Args:
424
+ name: Tool name
425
+ version: Version to deprecate
426
+ message: Optional deprecation message/migration guide
427
+
428
+ Raises:
429
+ ToolNotFoundError: If tool/version not found
430
+ """
431
+ if name not in self._tools or version not in self._tools[name]:
432
+ raise ToolNotFoundError(f"Tool '{name}' version '{version}' not found")
433
+
434
+ spec = self._tools[name][version]
435
+ spec.metadata.deprecated = True
436
+ spec.metadata.deprecated_message = message
437
+
438
+ def clear(self) -> None:
439
+ """Remove all tools from the registry."""
440
+ self._tools.clear()
441
+
442
+ def __len__(self) -> int:
443
+ """Return the number of registered tools (unique names)."""
444
+ return len(self._tools)
445
+
446
+ def total_versions(self) -> int:
447
+ """Return the total number of registered tool versions."""
448
+ return sum(len(versions) for versions in self._tools.values())
449
+
450
+ def __contains__(self, name: str) -> bool:
451
+ """Check if a tool is registered."""
452
+ return name in self._tools