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/schema.py ADDED
@@ -0,0 +1,480 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Schema definitions for Agent Tool Registry.
5
+
6
+ Defines the rigorous JSON/Pydantic schema for tool specifications,
7
+ similar to OpenAI Function Calling spec.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+ import time
14
+ from enum import Enum
15
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional
16
+
17
+ from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, field_validator
18
+
19
+ if TYPE_CHECKING:
20
+ pass
21
+
22
+
23
+ class ParameterType(str, Enum):
24
+ """Supported parameter types for tool inputs/outputs."""
25
+
26
+ STRING = "string"
27
+ INTEGER = "integer"
28
+ NUMBER = "number"
29
+ BOOLEAN = "boolean"
30
+ ARRAY = "array"
31
+ OBJECT = "object"
32
+
33
+
34
+ class ParameterSpec(BaseModel):
35
+ """Specification for a single parameter."""
36
+
37
+ name: str = Field(..., description="Parameter name")
38
+ type: ParameterType = Field(..., description="Parameter type")
39
+ description: str = Field(..., description="Human-readable description")
40
+ required: bool = Field(default=True, description="Whether parameter is required")
41
+ default: Optional[Any] = Field(default=None, description="Default value if not required")
42
+ enum: Optional[List[Any]] = Field(default=None, description="Allowed values (for enum types)")
43
+ items: Optional[Dict[str, Any]] = Field(
44
+ default=None, description="Array item schema (for array type)"
45
+ )
46
+ properties: Optional[Dict[str, Any]] = Field(
47
+ default=None, description="Object properties (for object type)"
48
+ )
49
+
50
+ @field_validator("default")
51
+ @classmethod
52
+ def validate_default(cls, v, info):
53
+ """Ensure default is only set for non-required parameters."""
54
+ if v is not None and info.data.get("required", True):
55
+ raise ValueError("Cannot set default value for required parameter")
56
+ return v
57
+
58
+
59
+ class SideEffect(str, Enum):
60
+ """Types of side effects a tool may have."""
61
+
62
+ NONE = "none"
63
+ READ = "read"
64
+ WRITE = "write"
65
+ DELETE = "delete"
66
+ NETWORK = "network"
67
+ FILESYSTEM = "filesystem"
68
+
69
+
70
+ class CostLevel(str, Enum):
71
+ """Cost level for tool execution."""
72
+
73
+ FREE = "free"
74
+ LOW = "low"
75
+ MEDIUM = "medium"
76
+ HIGH = "high"
77
+
78
+
79
+ class ToolMetadata(BaseModel):
80
+ """Metadata about a tool."""
81
+
82
+ name: str = Field(..., description="Unique tool identifier")
83
+ description: str = Field(..., description="Human-readable tool description")
84
+ version: str = Field(default="1.0.0", description="Semantic version (e.g., '1.0.0')")
85
+ author: Optional[str] = Field(default=None, description="Tool author")
86
+ cost: CostLevel = Field(default=CostLevel.FREE, description="Estimated execution cost")
87
+ side_effects: List[SideEffect] = Field(
88
+ default_factory=lambda: [SideEffect.NONE], description="Tool side effects"
89
+ )
90
+ tags: List[str] = Field(default_factory=list, description="Searchable tags")
91
+
92
+ # New fields for enhanced functionality
93
+ is_async: bool = Field(default=False, description="Whether tool supports async execution")
94
+ permissions: List[str] = Field(
95
+ default_factory=list, description="Required permissions/roles to access"
96
+ )
97
+ rate_limit: Optional[str] = Field(
98
+ default=None, description="Rate limit string (e.g., '10/minute')"
99
+ )
100
+ deprecated: bool = Field(default=False, description="Whether this tool version is deprecated")
101
+ deprecated_message: Optional[str] = Field(
102
+ default=None, description="Deprecation message/migration guide"
103
+ )
104
+
105
+ @field_validator("version")
106
+ @classmethod
107
+ def validate_version(cls, v: str) -> str:
108
+ """Validate semantic version format."""
109
+ import re
110
+
111
+ # Basic semver pattern
112
+ pattern = r"^\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?$"
113
+ if not re.match(pattern, v):
114
+ raise ValueError(f"Invalid version format: {v}. Expected semver (e.g., '1.0.0')")
115
+ return v
116
+
117
+ @property
118
+ def version_tuple(self) -> tuple:
119
+ """Get version as a comparable tuple."""
120
+ import re
121
+
122
+ # Extract major.minor.patch
123
+ match = re.match(r"^(\d+)\.(\d+)\.(\d+)", self.version)
124
+ if match:
125
+ return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
126
+ return (0, 0, 0)
127
+
128
+
129
+ class ToolSpec(BaseModel):
130
+ """Complete specification for a tool.
131
+
132
+ This is the core schema that defines what a tool looks like in the registry.
133
+ It does NOT execute the tool - it just describes it.
134
+ """
135
+
136
+ model_config = ConfigDict(arbitrary_types_allowed=True)
137
+
138
+ metadata: ToolMetadata = Field(..., description="Tool metadata")
139
+ parameters: List[ParameterSpec] = Field(default_factory=list, description="Input parameters")
140
+ returns: Optional[ParameterSpec] = Field(default=None, description="Return value specification")
141
+
142
+ # The actual callable - stored but never executed by the registry
143
+ # Use PrivateAttr for internal state that shouldn't be validated
144
+ _callable_func: Optional[Any] = PrivateAttr(default=None)
145
+
146
+ # Enhanced execution configuration
147
+ _retry_policy: Optional[Any] = PrivateAttr(default=None) # RetryPolicy
148
+ _rate_limit_policy: Optional[Any] = PrivateAttr(default=None) # RateLimitPolicy
149
+ _health_check: Optional[Any] = PrivateAttr(default=None) # HealthCheck
150
+ _access_policy: Optional[Any] = PrivateAttr(default=None) # AccessPolicy
151
+
152
+ @property
153
+ def name(self) -> str:
154
+ """Convenience property for tool name."""
155
+ return self.metadata.name
156
+
157
+ @property
158
+ def version(self) -> str:
159
+ """Convenience property for tool version."""
160
+ return self.metadata.version
161
+
162
+ @property
163
+ def is_async(self) -> bool:
164
+ """Check if tool supports async execution."""
165
+ return self.metadata.is_async
166
+
167
+ @property
168
+ def retry_policy(self) -> Optional[Any]:
169
+ """Get the retry policy if set."""
170
+ return self._retry_policy
171
+
172
+ @retry_policy.setter
173
+ def retry_policy(self, policy: Any) -> None:
174
+ """Set the retry policy."""
175
+ self._retry_policy = policy
176
+
177
+ @property
178
+ def rate_limit_policy(self) -> Optional[Any]:
179
+ """Get the rate limit policy if set."""
180
+ return self._rate_limit_policy
181
+
182
+ @rate_limit_policy.setter
183
+ def rate_limit_policy(self, policy: Any) -> None:
184
+ """Set the rate limit policy."""
185
+ self._rate_limit_policy = policy
186
+
187
+ @property
188
+ def health_check(self) -> Optional[Any]:
189
+ """Get the health check if set."""
190
+ return self._health_check
191
+
192
+ @health_check.setter
193
+ def health_check(self, check: Any) -> None:
194
+ """Set the health check."""
195
+ self._health_check = check
196
+
197
+ @property
198
+ def access_policy(self) -> Optional[Any]:
199
+ """Get the access policy if set."""
200
+ return self._access_policy
201
+
202
+ @access_policy.setter
203
+ def access_policy(self, policy: Any) -> None:
204
+ """Set the access policy."""
205
+ self._access_policy = policy
206
+
207
+ def to_openai_function_schema(self) -> Dict[str, Any]:
208
+ """Convert to OpenAI function calling format.
209
+
210
+ Returns:
211
+ Dictionary in OpenAI function calling format
212
+ """
213
+ properties = {}
214
+ required = []
215
+
216
+ for param in self.parameters:
217
+ prop_schema = {
218
+ "type": param.type.value,
219
+ "description": param.description,
220
+ }
221
+
222
+ if param.enum:
223
+ prop_schema["enum"] = param.enum
224
+ if param.items:
225
+ prop_schema["items"] = param.items
226
+ if param.properties:
227
+ prop_schema["properties"] = param.properties
228
+
229
+ properties[param.name] = prop_schema
230
+
231
+ if param.required:
232
+ required.append(param.name)
233
+
234
+ return {
235
+ "name": self.metadata.name,
236
+ "description": self.metadata.description,
237
+ "parameters": {
238
+ "type": "object",
239
+ "properties": properties,
240
+ "required": required,
241
+ },
242
+ }
243
+
244
+ def to_anthropic_tool_schema(self) -> Dict[str, Any]:
245
+ """Convert to Anthropic tool use format.
246
+
247
+ Returns:
248
+ Dictionary in Anthropic tool use format.
249
+ """
250
+ return {
251
+ "name": self.metadata.name,
252
+ "description": self.metadata.description,
253
+ "input_schema": {
254
+ "type": "object",
255
+ "properties": {
256
+ param.name: {
257
+ "type": param.type.value,
258
+ "description": param.description,
259
+ **({"enum": param.enum} if param.enum else {}),
260
+ **({"items": param.items} if param.items else {}),
261
+ }
262
+ for param in self.parameters
263
+ },
264
+ "required": [p.name for p in self.parameters if p.required],
265
+ },
266
+ }
267
+
268
+
269
+ class ToolHandle:
270
+ """Handle for executing a registered tool with all policies applied.
271
+
272
+ This is the public interface for tool execution, applying rate limiting,
273
+ retries, metrics collection, and access control automatically.
274
+
275
+ Example:
276
+ >>> tool = atr.get_tool("pdf_parser", version=">=1.0.0")
277
+ >>> result = await tool.call_async(file_path="doc.pdf")
278
+ >>> # or synchronously
279
+ >>> result = tool.call(file_path="doc.pdf")
280
+ """
281
+
282
+ def __init__(
283
+ self,
284
+ spec: ToolSpec,
285
+ container: Optional[Any] = None, # DependencyContainer
286
+ metrics_collector: Optional[Any] = None, # MetricsCollector
287
+ access_manager: Optional[Any] = None, # AccessControlManager
288
+ ):
289
+ """Initialize tool handle.
290
+
291
+ Args:
292
+ spec: The tool specification.
293
+ container: Optional dependency container for injection.
294
+ metrics_collector: Optional metrics collector.
295
+ access_manager: Optional access control manager.
296
+ """
297
+ self._spec = spec
298
+ self._container = container
299
+ self._metrics = metrics_collector
300
+ self._access_manager = access_manager
301
+
302
+ @property
303
+ def spec(self) -> ToolSpec:
304
+ """Get the underlying tool specification."""
305
+ return self._spec
306
+
307
+ @property
308
+ def name(self) -> str:
309
+ """Get tool name."""
310
+ return self._spec.name
311
+
312
+ @property
313
+ def version(self) -> str:
314
+ """Get tool version."""
315
+ return self._spec.version
316
+
317
+ @property
318
+ def is_async(self) -> bool:
319
+ """Check if tool supports async."""
320
+ return self._spec.is_async
321
+
322
+ def call(self, *args: Any, **kwargs: Any) -> Any:
323
+ """Execute the tool synchronously with all policies.
324
+
325
+ Args:
326
+ *args: Positional arguments.
327
+ **kwargs: Keyword arguments.
328
+
329
+ Returns:
330
+ The tool's return value.
331
+
332
+ Raises:
333
+ ValueError: If tool has no callable.
334
+ RateLimitExceeded: If rate limited.
335
+ RetryExhausted: If all retries fail.
336
+ AccessDeniedError: If access is denied.
337
+ """
338
+ if self._spec._callable_func is None:
339
+ raise ValueError(f"Tool '{self.name}' has no callable function")
340
+
341
+ start_time = time.perf_counter()
342
+ error = None
343
+ rate_limited = False
344
+
345
+ try:
346
+ # Apply rate limiting
347
+ if self._spec._rate_limit_policy and not self._spec._rate_limit_policy.acquire(
348
+ blocking=True, timeout=30
349
+ ):
350
+ rate_limited = True
351
+ from atr.policies import RateLimitExceeded
352
+
353
+ raise RateLimitExceeded(f"Rate limit exceeded for tool '{self.name}'")
354
+
355
+ # Inject dependencies if container available
356
+ if self._container:
357
+ from atr.injection import InjectionResolver
358
+
359
+ resolver = InjectionResolver(self._container)
360
+ kwargs = resolver.resolve_parameters(self._spec._callable_func, args, kwargs)
361
+ args = ()
362
+
363
+ # Execute with retry policy if configured
364
+ if self._spec._retry_policy:
365
+ from atr.policies import with_retry
366
+
367
+ result = with_retry(
368
+ self._spec._retry_policy, self._spec._callable_func, *args, **kwargs
369
+ )
370
+ else:
371
+ result = self._spec._callable_func(*args, **kwargs)
372
+
373
+ return result
374
+
375
+ except Exception as e:
376
+ error = e
377
+ raise
378
+ finally:
379
+ # Record metrics
380
+ if self._metrics:
381
+ latency_ms = (time.perf_counter() - start_time) * 1000
382
+ self._metrics.record_call(
383
+ tool_name=self.name,
384
+ latency_ms=latency_ms,
385
+ success=(error is None),
386
+ error=error,
387
+ rate_limited=rate_limited,
388
+ )
389
+
390
+ async def call_async(self, *args: Any, **kwargs: Any) -> Any:
391
+ """Execute the tool asynchronously with all policies.
392
+
393
+ Args:
394
+ *args: Positional arguments.
395
+ **kwargs: Keyword arguments.
396
+
397
+ Returns:
398
+ The tool's return value.
399
+
400
+ Raises:
401
+ ValueError: If tool has no callable.
402
+ RateLimitExceeded: If rate limited.
403
+ RetryExhausted: If all retries fail.
404
+ AccessDeniedError: If access is denied.
405
+ """
406
+ if self._spec._callable_func is None:
407
+ raise ValueError(f"Tool '{self.name}' has no callable function")
408
+
409
+ start_time = time.perf_counter()
410
+ error = None
411
+ rate_limited = False
412
+
413
+ try:
414
+ # Apply rate limiting
415
+ if (
416
+ self._spec._rate_limit_policy
417
+ and not await self._spec._rate_limit_policy.acquire_async(blocking=True, timeout=30)
418
+ ):
419
+ rate_limited = True
420
+ from atr.policies import RateLimitExceeded
421
+
422
+ raise RateLimitExceeded(f"Rate limit exceeded for tool '{self.name}'")
423
+
424
+ # Inject dependencies if container available
425
+ if self._container:
426
+ from atr.injection import InjectionResolver
427
+
428
+ resolver = InjectionResolver(self._container)
429
+ kwargs = resolver.resolve_parameters(self._spec._callable_func, args, kwargs)
430
+ args = ()
431
+
432
+ # Execute with retry policy if configured
433
+ if self._spec._retry_policy:
434
+ from atr.policies import with_retry_async
435
+
436
+ result = await with_retry_async(
437
+ self._spec._retry_policy, self._spec._callable_func, *args, **kwargs
438
+ )
439
+ else:
440
+ func = self._spec._callable_func
441
+ result = func(*args, **kwargs)
442
+ if asyncio.iscoroutine(result):
443
+ result = await result
444
+
445
+ return result
446
+
447
+ except Exception as e:
448
+ error = e
449
+ raise
450
+ finally:
451
+ # Record metrics
452
+ if self._metrics:
453
+ latency_ms = (time.perf_counter() - start_time) * 1000
454
+ self._metrics.record_call(
455
+ tool_name=self.name,
456
+ latency_ms=latency_ms,
457
+ success=(error is None),
458
+ error=error,
459
+ rate_limited=rate_limited,
460
+ )
461
+
462
+ def check_health(self) -> Optional[Any]:
463
+ """Run health check if configured.
464
+
465
+ Returns:
466
+ HealthCheckResult or None if no health check configured.
467
+ """
468
+ if self._spec._health_check:
469
+ return self._spec._health_check.check()
470
+ return None
471
+
472
+ async def check_health_async(self) -> Optional[Any]:
473
+ """Run health check asynchronously.
474
+
475
+ Returns:
476
+ HealthCheckResult or None if no health check configured.
477
+ """
478
+ if self._spec._health_check:
479
+ return await self._spec._health_check.check_async()
480
+ return None
@@ -0,0 +1,75 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Safe Tool Plugins for Agent Tool Registry (ATR).
5
+
6
+ This package provides pre-built, security-hardened tools that agents can use
7
+ safely without risk of unauthorized access or dangerous operations.
8
+
9
+ All tools in this package follow the principle of least privilege:
10
+ - Read-only operations where possible
11
+ - Sandboxed file access
12
+ - Rate limiting on network operations
13
+ - Input validation and sanitization
14
+ - No shell execution
15
+
16
+ Available Tools:
17
+ - HttpClientTool: Safe HTTP requests with URL whitelisting
18
+ - FileReaderTool: Read-only file access with path sandboxing
19
+ - JsonParserTool: Safe JSON/YAML parsing
20
+ - CalculatorTool: Safe mathematical operations
21
+ - DateTimeTool: Timezone-aware datetime operations
22
+ - TextTool: Safe text processing operations
23
+
24
+ Example:
25
+ >>> from atr.tools.safe import HttpClientTool, FileReaderTool
26
+ >>>
27
+ >>> # Create tools with restrictions
28
+ >>> http = HttpClientTool(
29
+ ... allowed_domains=["api.example.com"],
30
+ ... rate_limit=10 # requests per minute
31
+ ... )
32
+ >>>
33
+ >>> reader = FileReaderTool(
34
+ ... sandbox_path="/data/safe",
35
+ ... max_file_size=1_000_000 # 1MB
36
+ ... )
37
+ """
38
+
39
+ from typing import List
40
+
41
+ __all__: List[str] = [
42
+ "HttpClientTool",
43
+ "FileReaderTool",
44
+ "JsonParserTool",
45
+ "CalculatorTool",
46
+ "DateTimeTool",
47
+ "TextTool",
48
+ "create_safe_toolkit",
49
+ ]
50
+
51
+
52
+ def __getattr__(name: str):
53
+ """Lazy import tools."""
54
+ if name == "HttpClientTool":
55
+ from atr.tools.safe.http_client import HttpClientTool
56
+ return HttpClientTool
57
+ elif name == "FileReaderTool":
58
+ from atr.tools.safe.file_reader import FileReaderTool
59
+ return FileReaderTool
60
+ elif name == "JsonParserTool":
61
+ from atr.tools.safe.json_parser import JsonParserTool
62
+ return JsonParserTool
63
+ elif name == "CalculatorTool":
64
+ from atr.tools.safe.calculator import CalculatorTool
65
+ return CalculatorTool
66
+ elif name == "DateTimeTool":
67
+ from atr.tools.safe.datetime_tool import DateTimeTool
68
+ return DateTimeTool
69
+ elif name == "TextTool":
70
+ from atr.tools.safe.text_tool import TextTool
71
+ return TextTool
72
+ elif name == "create_safe_toolkit":
73
+ from atr.tools.safe.toolkit import create_safe_toolkit
74
+ return create_safe_toolkit
75
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")