domyn 0.0.1__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.

Potentially problematic release.


This version of domyn might be problematic. Click here for more details.

Files changed (313) hide show
  1. domyn/__init__.py +14 -0
  2. domyn/agents/__init__.py +108 -0
  3. domyn/agents/adapters/__init__.py +6 -0
  4. domyn/agents/adapters/_invocation.py +97 -0
  5. domyn/agents/adapters/domyn_agent.py +407 -0
  6. domyn/agents/adapters/langgraph.py +347 -0
  7. domyn/agents/agents/__init__.py +48 -0
  8. domyn/agents/agents/agent.py +780 -0
  9. domyn/agents/agents/base.py +77 -0
  10. domyn/agents/agents/delegate_agent.py +405 -0
  11. domyn/agents/agents/wrapped.py +118 -0
  12. domyn/agents/approvals/__init__.py +61 -0
  13. domyn/agents/approvals/models.py +205 -0
  14. domyn/agents/approvals/policy.py +185 -0
  15. domyn/agents/approvals/store.py +327 -0
  16. domyn/agents/approvals/subject.py +137 -0
  17. domyn/agents/audio/__init__.py +21 -0
  18. domyn/agents/audio/base.py +88 -0
  19. domyn/agents/audio/convert.py +78 -0
  20. domyn/agents/audio/local.py +214 -0
  21. domyn/agents/audio/models.py +34 -0
  22. domyn/agents/audio/openai_compatible.py +138 -0
  23. domyn/agents/channels/__init__.py +16 -0
  24. domyn/agents/channels/_parts.py +24 -0
  25. domyn/agents/channels/_voice.py +108 -0
  26. domyn/agents/channels/cursor_store.py +79 -0
  27. domyn/agents/channels/domyn_relay.py +339 -0
  28. domyn/agents/channels/slack.py +262 -0
  29. domyn/agents/channels/telegram.py +253 -0
  30. domyn/agents/channels/whatsapp.py +367 -0
  31. domyn/agents/cli/README.md +171 -0
  32. domyn/agents/cli/cli.py +102 -0
  33. domyn/agents/cli/cli_dependencies.py +78 -0
  34. domyn/agents/cli/commands/__init__.py +11 -0
  35. domyn/agents/cli/commands/export/__init__.py +3 -0
  36. domyn/agents/cli/commands/export/command.py +60 -0
  37. domyn/agents/cli/commands/init/__init__.py +5 -0
  38. domyn/agents/cli/commands/init/command.py +351 -0
  39. domyn/agents/cli/commands/run/__init__.py +5 -0
  40. domyn/agents/cli/commands/run/command.py +778 -0
  41. domyn/agents/cli/commands/serve/__init__.py +5 -0
  42. domyn/agents/cli/commands/serve/command.py +936 -0
  43. domyn/agents/cli/commands/serve/server.py +158 -0
  44. domyn/agents/cli/commands/setup/__init__.py +3 -0
  45. domyn/agents/cli/commands/setup/command.py +134 -0
  46. domyn/agents/cli/commands/skills/__init__.py +3 -0
  47. domyn/agents/cli/commands/skills/command.py +206 -0
  48. domyn/agents/cli/main.py +46 -0
  49. domyn/agents/cli/project.py +174 -0
  50. domyn/agents/cli/utils.py +31 -0
  51. domyn/agents/conversation_manager/__init__.py +17 -0
  52. domyn/agents/conversation_manager/base.py +341 -0
  53. domyn/agents/conversation_manager/in_memory.py +281 -0
  54. domyn/agents/conversation_manager/sqlite.py +479 -0
  55. domyn/agents/core/__init__.py +445 -0
  56. domyn/agents/core/context.py +91 -0
  57. domyn/agents/core/decorators.py +247 -0
  58. domyn/agents/core/documents.py +658 -0
  59. domyn/agents/core/exceptions.py +5 -0
  60. domyn/agents/core/interfaces.py +57 -0
  61. domyn/agents/core/utils.py +231 -0
  62. domyn/agents/core/visibility.py +43 -0
  63. domyn/agents/decisions/__init__.py +138 -0
  64. domyn/agents/decisions/approvals.py +147 -0
  65. domyn/agents/decisions/base.py +161 -0
  66. domyn/agents/decisions/config.py +148 -0
  67. domyn/agents/decisions/context.py +134 -0
  68. domyn/agents/decisions/events.py +73 -0
  69. domyn/agents/decisions/llm.py +322 -0
  70. domyn/agents/decisions/models.py +233 -0
  71. domyn/agents/decisions/none.py +35 -0
  72. domyn/agents/decisions/runtime.py +275 -0
  73. domyn/agents/decisions/sensitivity.py +180 -0
  74. domyn/agents/decisions/system_one.py +221 -0
  75. domyn/agents/decisions/tools.py +140 -0
  76. domyn/agents/decorators.py +10 -0
  77. domyn/agents/hooks/__init__.py +143 -0
  78. domyn/agents/hooks/base.py +134 -0
  79. domyn/agents/hooks/function_hook.py +516 -0
  80. domyn/agents/instructions/__init__.py +101 -0
  81. domyn/agents/instructions/conditional.py +203 -0
  82. domyn/agents/instructions/discovery.py +114 -0
  83. domyn/agents/instructions/models.py +147 -0
  84. domyn/agents/instructions/runtime.py +103 -0
  85. domyn/agents/instructions/sources.py +206 -0
  86. domyn/agents/integrations/__init__.py +0 -0
  87. domyn/agents/integrations/domyn/__init__.py +8 -0
  88. domyn/agents/integrations/domyn/domyn_platform.py +238 -0
  89. domyn/agents/integrations/domyn_platform_sdk.py +263 -0
  90. domyn/agents/integrations/hermes_platform_gateway/__init__.py +715 -0
  91. domyn/agents/integrations/hermes_platform_gateway/_context.py +43 -0
  92. domyn/agents/integrations/hermes_platform_gateway/adapter.py +1872 -0
  93. domyn/agents/integrations/hermes_platform_gateway/client.py +440 -0
  94. domyn/agents/integrations/hermes_platform_gateway/relay_client.py +189 -0
  95. domyn/agents/integrations/hermes_platform_gateway/schema.py +49 -0
  96. domyn/agents/integrations/langgraph/README.md +198 -0
  97. domyn/agents/integrations/langgraph/__init__.py +25 -0
  98. domyn/agents/integrations/langgraph/domyn_platform.py +230 -0
  99. domyn/agents/integrations/langgraph/handler.py +1020 -0
  100. domyn/agents/integrations/langgraph/run_state.py +157 -0
  101. domyn/agents/integrations/langgraph/utils.py +60 -0
  102. domyn/agents/integrations/utils.py +91 -0
  103. domyn/agents/interfaces/__init__.py +18 -0
  104. domyn/agents/interfaces/adapter.py +62 -0
  105. domyn/agents/interfaces/auth.py +19 -0
  106. domyn/agents/interfaces/channel.py +51 -0
  107. domyn/agents/interfaces/cli/__init__.py +10 -0
  108. domyn/agents/interfaces/cli/approval.py +403 -0
  109. domyn/agents/interfaces/cli/assets/logo_100.ans +11 -0
  110. domyn/agents/interfaces/cli/assets/logo_100.frames.gz +0 -0
  111. domyn/agents/interfaces/cli/assets/logo_120.ans +13 -0
  112. domyn/agents/interfaces/cli/assets/logo_120.frames.gz +0 -0
  113. domyn/agents/interfaces/cli/assets/logo_150.ans +17 -0
  114. domyn/agents/interfaces/cli/assets/logo_150.frames.gz +0 -0
  115. domyn/agents/interfaces/cli/banner.py +305 -0
  116. domyn/agents/interfaces/cli/calls.py +228 -0
  117. domyn/agents/interfaces/cli/commands.py +133 -0
  118. domyn/agents/interfaces/cli/config.py +1838 -0
  119. domyn/agents/interfaces/cli/context_view.py +186 -0
  120. domyn/agents/interfaces/cli/conversations.py +273 -0
  121. domyn/agents/interfaces/cli/export.py +1275 -0
  122. domyn/agents/interfaces/cli/grants.py +175 -0
  123. domyn/agents/interfaces/cli/inventory.py +63 -0
  124. domyn/agents/interfaces/cli/markdown.py +736 -0
  125. domyn/agents/interfaces/cli/processes_view.py +160 -0
  126. domyn/agents/interfaces/cli/project_import.py +243 -0
  127. domyn/agents/interfaces/cli/project_trust.py +68 -0
  128. domyn/agents/interfaces/cli/prompt.py +919 -0
  129. domyn/agents/interfaces/cli/renderer.py +859 -0
  130. domyn/agents/interfaces/cli/repl.py +1746 -0
  131. domyn/agents/interfaces/cli/select.py +619 -0
  132. domyn/agents/interfaces/cli/setup.py +1934 -0
  133. domyn/agents/interfaces/cli/skills_view.py +422 -0
  134. domyn/agents/interfaces/cli/spinner.py +268 -0
  135. domyn/agents/interfaces/cli/theme.py +274 -0
  136. domyn/agents/interfaces/cli/voice.py +339 -0
  137. domyn/agents/interfaces/cursor_store.py +28 -0
  138. domyn/agents/interfaces/normalizer.py +44 -0
  139. domyn/agents/llm/__init__.py +116 -0
  140. domyn/agents/llm/anthropic.py +492 -0
  141. domyn/agents/llm/base.py +395 -0
  142. domyn/agents/llm/cerebras.py +406 -0
  143. domyn/agents/llm/context_window.py +232 -0
  144. domyn/agents/llm/context_windows.json +78 -0
  145. domyn/agents/llm/custom.py +310 -0
  146. domyn/agents/llm/delegate.py +63 -0
  147. domyn/agents/llm/domyn.py +268 -0
  148. domyn/agents/llm/open_router.py +480 -0
  149. domyn/agents/llm/openai.py +471 -0
  150. domyn/agents/llm/vllm.py +423 -0
  151. domyn/agents/loader/__init__.py +120 -0
  152. domyn/agents/loader/config.py +1080 -0
  153. domyn/agents/logger/__init__.py +115 -0
  154. domyn/agents/memory/managers/__init__.py +17 -0
  155. domyn/agents/memory/managers/base.py +240 -0
  156. domyn/agents/memory/managers/local.py +164 -0
  157. domyn/agents/memory/managers/remote.py +60 -0
  158. domyn/agents/planner_strategy/__init__.py +308 -0
  159. domyn/agents/planner_strategy/base.py +66 -0
  160. domyn/agents/planner_strategy/context_injection.py +100 -0
  161. domyn/agents/planner_strategy/context_management/__init__.py +0 -0
  162. domyn/agents/planner_strategy/context_management/base.py +73 -0
  163. domyn/agents/planner_strategy/context_management/budget.py +231 -0
  164. domyn/agents/planner_strategy/context_management/compaction.py +1778 -0
  165. domyn/agents/planner_strategy/context_management/full_messages.py +80 -0
  166. domyn/agents/planner_strategy/context_management/summary.py +307 -0
  167. domyn/agents/planner_strategy/context_management/tool_use.py +747 -0
  168. domyn/agents/planner_strategy/prompting/__init__.py +1 -0
  169. domyn/agents/planner_strategy/prompting/base.py +372 -0
  170. domyn/agents/planner_strategy/prompting/data.py +46 -0
  171. domyn/agents/planner_strategy/prompting/json_prompting.py +380 -0
  172. domyn/agents/planner_strategy/prompting/messages_building.py +59 -0
  173. domyn/agents/planner_strategy/prompting/structural_tags_prompting.py +461 -0
  174. domyn/agents/planner_strategy/prompting/utils.py +152 -0
  175. domyn/agents/planner_strategy/react.py +665 -0
  176. domyn/agents/planner_strategy/tool_use.py +1021 -0
  177. domyn/agents/planner_strategy/tool_use_thought.py +658 -0
  178. domyn/agents/planner_strategy/utils.py +361 -0
  179. domyn/agents/plugins/__init__.py +5 -0
  180. domyn/agents/registry/__init__.py +23 -0
  181. domyn/agents/registry/agents.py +48 -0
  182. domyn/agents/registry/hooks.py +36 -0
  183. domyn/agents/registry/llm.py +55 -0
  184. domyn/agents/registry/planner_strategy.py +47 -0
  185. domyn/agents/registry/tools.py +40 -0
  186. domyn/agents/runner/__init__.py +4947 -0
  187. domyn/agents/runner/sse_transport.py +520 -0
  188. domyn/agents/runner/transport.py +303 -0
  189. domyn/agents/runner/websocket_transport.py +408 -0
  190. domyn/agents/scripts/__init__.py +7 -0
  191. domyn/agents/scripts/pdf_reader.py +184 -0
  192. domyn/agents/server.py +192 -0
  193. domyn/agents/skills/__init__.py +86 -0
  194. domyn/agents/skills/builtin/cli/domyn-cli/SKILL.md +346 -0
  195. domyn/agents/skills/builtin/cli/domyn-docs/SKILL.md +71 -0
  196. domyn/agents/skills/builtin/cli/domyn-docs/pages/cli/configuration.md +191 -0
  197. domyn/agents/skills/builtin/cli/domyn-docs/pages/cli/sessions.md +120 -0
  198. domyn/agents/skills/builtin/cli/domyn-docs/pages/cli/tools-and-approvals.md +89 -0
  199. domyn/agents/skills/builtin/cli/domyn-docs/pages/getting-started/installation.md +126 -0
  200. domyn/agents/skills/builtin/cli/domyn-docs/pages/getting-started/quickstart-cli.md +89 -0
  201. domyn/agents/skills/builtin/cli/domyn-docs/pages/getting-started/quickstart-library.md +97 -0
  202. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/approvals.md +347 -0
  203. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/configuration.md +293 -0
  204. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/context-compaction.md +150 -0
  205. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/conversations-and-memory.md +157 -0
  206. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/decision-models.md +211 -0
  207. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/events-and-streaming.md +163 -0
  208. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/hooks.md +234 -0
  209. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/llm-providers.md +225 -0
  210. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/orchestration.md +172 -0
  211. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/planner-strategies.md +139 -0
  212. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/remote-agents.md +279 -0
  213. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/skills.md +290 -0
  214. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/standing-instructions.md +129 -0
  215. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/tools.md +310 -0
  216. domyn/agents/skills/builtin/cli/domyn-docs/pages/guides/transcription.md +122 -0
  217. domyn/agents/skills/builtin/cli/domyn-docs/pages/index.md +41 -0
  218. domyn/agents/skills/builtin/cli/domyn-docs/pages/reference/cli.md +160 -0
  219. domyn/agents/skills/builtin/cli/domyn-docs/pages/reference/events.md +104 -0
  220. domyn/agents/skills/builtin/cli/domyn-docs/pages/reference/yaml-schema.md +172 -0
  221. domyn/agents/skills/builtin/data/data-analysis/SKILL.md +397 -0
  222. domyn/agents/skills/builtin/data/data-analysis/scripts/common.py +211 -0
  223. domyn/agents/skills/builtin/data/data-analysis/scripts/default_analysis.py +501 -0
  224. domyn/agents/skills/builtin/data/data-analysis/scripts/profile_data.py +290 -0
  225. domyn/agents/skills/builtin/data/data-analysis/scripts/timeseries_analysis.py +390 -0
  226. domyn/agents/skills/builtin/data/data_utils.py +479 -0
  227. domyn/agents/skills/builtin/data/prepare_series.py +425 -0
  228. domyn/agents/skills/builtin/data/prepare_table.py +360 -0
  229. domyn/agents/skills/builtin/data/series_format.py +304 -0
  230. domyn/agents/skills/builtin/data/tabular-classification-regression/SKILL.md +342 -0
  231. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/classification_baseline.py +135 -0
  232. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/classification_catboost.py +166 -0
  233. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/classification_compare.py +209 -0
  234. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/common.py +652 -0
  235. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/make_split.py +67 -0
  236. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/regression_baseline.py +108 -0
  237. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/regression_catboost.py +144 -0
  238. domyn/agents/skills/builtin/data/tabular-classification-regression/scripts/regression_compare.py +199 -0
  239. domyn/agents/skills/builtin/data/time-series-forecasting/SKILL.md +349 -0
  240. domyn/agents/skills/builtin/data/time-series-forecasting/scripts/common.py +474 -0
  241. domyn/agents/skills/builtin/data/time-series-forecasting/scripts/forecast_baseline.py +213 -0
  242. domyn/agents/skills/builtin/data/time-series-forecasting/scripts/forecast_catboost.py +287 -0
  243. domyn/agents/skills/builtin/data/time-series-forecasting/scripts/forecast_compare.py +398 -0
  244. domyn/agents/skills/builtin/data/time-series-forecasting/scripts/forecast_split.py +64 -0
  245. domyn/agents/skills/builtin/productivity/brainstorming/SKILL.md +184 -0
  246. domyn/agents/skills/builtin/productivity/communication/SKILL.md +126 -0
  247. domyn/agents/skills/builtin/productivity/documents/SKILL.md +218 -0
  248. domyn/agents/skills/builtin/productivity/documents/scripts/check_pdf.py +296 -0
  249. domyn/agents/skills/builtin/productivity/documents/scripts/pdf_layout.json +76 -0
  250. domyn/agents/skills/builtin/productivity/documents/scripts/pdf_layout.py +632 -0
  251. domyn/agents/skills/builtin/productivity/presentations/SKILL.md +463 -0
  252. domyn/agents/skills/builtin/productivity/presentations/scripts/check_pptx.py +886 -0
  253. domyn/agents/skills/builtin/productivity/presentations/scripts/slides.py +1102 -0
  254. domyn/agents/skills/builtin/productivity/presentations/template/layouts.pptx +0 -0
  255. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-Bold.ttf +0 -0
  256. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-BoldItalic.ttf +0 -0
  257. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-Italic.ttf +0 -0
  258. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-Light.ttf +0 -0
  259. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-LightItalic.ttf +0 -0
  260. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-Medium.ttf +0 -0
  261. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-MediumItalic.ttf +0 -0
  262. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-Regular.ttf +0 -0
  263. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-SemiBold.ttf +0 -0
  264. domyn/agents/skills/builtin/resources/assets/fonts/DMSans-SemiBoldItalic.ttf +0 -0
  265. domyn/agents/skills/builtin/resources/assets/fonts/OFL-LICENSE.txt +93 -0
  266. domyn/agents/skills/builtin/resources/palette.json +89 -0
  267. domyn/agents/skills/builtin/resources/plotly_style.py +170 -0
  268. domyn/agents/skills/builtin/resources/seaborn_style.py +310 -0
  269. domyn/agents/skills/builtin/resources/typography.json +41 -0
  270. domyn/agents/skills/builtin/visualization/charts/SKILL.md +173 -0
  271. domyn/agents/skills/builtin/visualization/interactive-charts/SKILL.md +135 -0
  272. domyn/agents/skills/catalog.py +279 -0
  273. domyn/agents/skills/external_files.py +82 -0
  274. domyn/agents/skills/integration.py +241 -0
  275. domyn/agents/skills/layout.py +111 -0
  276. domyn/agents/skills/local.py +110 -0
  277. domyn/agents/skills/models.py +228 -0
  278. domyn/agents/skills/parser.py +192 -0
  279. domyn/agents/skills/remote.py +19 -0
  280. domyn/agents/skills/runtime.py +392 -0
  281. domyn/agents/skills/search.py +278 -0
  282. domyn/agents/skills/selectors.py +409 -0
  283. domyn/agents/skills/sources.py +357 -0
  284. domyn/agents/skills/turn.py +100 -0
  285. domyn/agents/tools/__init__.py +38 -0
  286. domyn/agents/tools/base.py +669 -0
  287. domyn/agents/tools/builtin/__init__.py +259 -0
  288. domyn/agents/tools/builtin/backends.py +260 -0
  289. domyn/agents/tools/builtin/browser.py +331 -0
  290. domyn/agents/tools/builtin/browser_install.py +224 -0
  291. domyn/agents/tools/builtin/browser_sessions.py +922 -0
  292. domyn/agents/tools/builtin/files.py +708 -0
  293. domyn/agents/tools/builtin/processes.py +1084 -0
  294. domyn/agents/tools/builtin/session.py +258 -0
  295. domyn/agents/tools/builtin/shell.py +859 -0
  296. domyn/agents/tools/builtin/workspace.py +170 -0
  297. domyn/agents/tools/delegate_tool.py +165 -0
  298. domyn/agents/tools/function_tool.py +453 -0
  299. domyn/agents/tools/mcp/__init__.py +14 -0
  300. domyn/agents/tools/mcp/mcp_config.py +138 -0
  301. domyn/agents/tools/mcp/mcp_tool.py +845 -0
  302. domyn/agents/tools/mcp/oauth_providers.py +505 -0
  303. domyn/agents/tools/read_tool_result.py +271 -0
  304. domyn/agents/tools/rest_function_tool.py +167 -0
  305. domyn/agents/tools/schema.py +461 -0
  306. domyn/agents/tools/streamable_function_tool.py +68 -0
  307. domyn/agents/tracing/__init__.py +128 -0
  308. domyn-0.0.1.dist-info/METADATA +159 -0
  309. domyn-0.0.1.dist-info/RECORD +313 -0
  310. domyn-0.0.1.dist-info/WHEEL +4 -0
  311. domyn-0.0.1.dist-info/entry_points.txt +2 -0
  312. domyn-0.0.1.dist-info/licenses/LICENSE +202 -0
  313. domyn-0.0.1.dist-info/licenses/NOTICE +21 -0
domyn/__init__.py ADDED
@@ -0,0 +1,14 @@
1
+ """Domyn.
2
+
3
+ The top-level package of the Domyn distribution. Each product is a subpackage:
4
+ ``domyn.agents`` is the agent framework. Importing ``domyn`` imports none of them.
5
+ """
6
+
7
+ from importlib.metadata import PackageNotFoundError, version
8
+
9
+ try:
10
+ __version__ = version("domyn")
11
+ except PackageNotFoundError:
12
+ __version__ = "unknown"
13
+
14
+ __all__ = ["__version__"]
@@ -0,0 +1,108 @@
1
+ """Domyn Agents.
2
+
3
+ Importing the package imports none of its subpackages, so a process that needs
4
+ one light module does not pay for the agent machinery. ``decorators`` and
5
+ ``register_transport`` are imported on first use.
6
+ """
7
+
8
+ import warnings
9
+ from importlib import import_module
10
+ from importlib.metadata import PackageNotFoundError, version
11
+ from typing import TYPE_CHECKING, Any
12
+
13
+ warnings.filterwarnings(
14
+ "ignore", category=UserWarning, message=r"Field name .* shadows an attribute in parent"
15
+ )
16
+
17
+ try:
18
+ __version__ = version("domyn")
19
+ except PackageNotFoundError:
20
+ __version__ = "unknown"
21
+
22
+ __all__ = [
23
+ "Agent",
24
+ "AnthropicProvider",
25
+ "ApprovalType",
26
+ "BaseAgent",
27
+ "BaseEvent",
28
+ "ContextVisibility",
29
+ "DelegateAgent",
30
+ "ExecutionEventType",
31
+ "FunctionTool",
32
+ "HandoffScope",
33
+ "InteractionContext",
34
+ "MCPTool",
35
+ "OpenAIProvider",
36
+ "OpenRouterProvider",
37
+ "Part",
38
+ "Runner",
39
+ "StreamableFunctionTool",
40
+ "VLLMProvider",
41
+ "__version__",
42
+ "decorators",
43
+ "load_application_from_file",
44
+ "register_transport",
45
+ ]
46
+
47
+ # Public names, resolved on first use from the subpackage that owns them, so that
48
+ # ``from domyn.agents import Agent`` works while importing the package imports none
49
+ # of its subpackages.
50
+ _LAZY_EXPORTS = {
51
+ "Agent": "domyn.agents.agents",
52
+ "ContextVisibility": "domyn.agents.agents",
53
+ "HandoffScope": "domyn.agents.agents",
54
+ "ApprovalType": "domyn.agents.core",
55
+ "DelegateAgent": "domyn.agents.agents",
56
+ "BaseAgent": "domyn.agents.core",
57
+ "InteractionContext": "domyn.agents.core",
58
+ "BaseEvent": "domyn.agents.core",
59
+ "ExecutionEventType": "domyn.agents.core",
60
+ "Part": "domyn.agents.core",
61
+ "Runner": "domyn.agents.runner",
62
+ "FunctionTool": "domyn.agents.tools",
63
+ "StreamableFunctionTool": "domyn.agents.tools",
64
+ "MCPTool": "domyn.agents.tools",
65
+ "VLLMProvider": "domyn.agents.llm",
66
+ "OpenAIProvider": "domyn.agents.llm",
67
+ "OpenRouterProvider": "domyn.agents.llm",
68
+ "AnthropicProvider": "domyn.agents.llm",
69
+ "load_application_from_file": "domyn.agents.loader",
70
+ }
71
+
72
+ if TYPE_CHECKING:
73
+ from domyn.agents.agents import Agent as Agent
74
+ from domyn.agents.agents import ContextVisibility as ContextVisibility
75
+ from domyn.agents.agents import DelegateAgent as DelegateAgent
76
+ from domyn.agents.agents import HandoffScope as HandoffScope
77
+ from domyn.agents.core import ApprovalType as ApprovalType
78
+ from domyn.agents.core import BaseAgent as BaseAgent
79
+ from domyn.agents.core import BaseEvent as BaseEvent
80
+ from domyn.agents.core import ExecutionEventType as ExecutionEventType
81
+ from domyn.agents.core import InteractionContext as InteractionContext
82
+ from domyn.agents.core import Part as Part
83
+ from domyn.agents.core import decorators as decorators
84
+ from domyn.agents.llm import AnthropicProvider as AnthropicProvider
85
+ from domyn.agents.llm import OpenAIProvider as OpenAIProvider
86
+ from domyn.agents.llm import OpenRouterProvider as OpenRouterProvider
87
+ from domyn.agents.llm import VLLMProvider as VLLMProvider
88
+ from domyn.agents.loader import load_application_from_file as load_application_from_file
89
+ from domyn.agents.runner import Runner as Runner
90
+ from domyn.agents.runner.transport import register_transport as register_transport
91
+ from domyn.agents.tools import FunctionTool as FunctionTool
92
+ from domyn.agents.tools import MCPTool as MCPTool
93
+ from domyn.agents.tools import StreamableFunctionTool as StreamableFunctionTool
94
+
95
+
96
+ def __getattr__(name: str) -> Any:
97
+ if name == "decorators":
98
+ return import_module("domyn.agents.decorators")
99
+ if name == "register_transport":
100
+ from domyn.agents.runner.transport import register_transport
101
+
102
+ globals()[name] = register_transport
103
+ return register_transport
104
+ if name in _LAZY_EXPORTS:
105
+ value = getattr(import_module(_LAZY_EXPORTS[name]), name)
106
+ globals()[name] = value
107
+ return value
108
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1,6 @@
1
+ """DomynAgentAdapter and LangGraphAdapter — FrameworkAdapter implementations."""
2
+
3
+ from domyn.agents.adapters.domyn_agent import DomynAgentAdapter
4
+ from domyn.agents.adapters.langgraph import LangGraphAdapter
5
+
6
+ __all__ = ["DomynAgentAdapter", "LangGraphAdapter"]
@@ -0,0 +1,97 @@
1
+ """Shared per-invocation plumbing for FrameworkAdapter implementations.
2
+
3
+ LangGraphAdapter and DomynAgentAdapter each drive a fresh asyncio.Task for
4
+ their delegate/platform-tool callback (``call_platform_tool`` /
5
+ ``_make_tool_call``) — LangGraph's ``ainvoke()`` and
6
+ ``Runner._merge_with_injections`` both schedule every step of a turn via
7
+ ``asyncio.ensure_future``/``asyncio.create_task``, so ``asyncio.current_task()``
8
+ inside that callback is never the task ``invoke()``'s ``_runner_task()``
9
+ registered anything under. A ``contextvars.ContextVar`` survives this where a
10
+ ``dict[asyncio.Task, ...]`` would not: a ``contextvars.Context`` is copied into
11
+ every child task at the moment it is spawned from a task carrying it, so
12
+ ``.get()`` finds the right value regardless of which disposable child task is
13
+ executing.
14
+
15
+ ``InvocationCtx`` fields are *snapshots* taken at ``invoke()`` time, not a live
16
+ reference to the inbound ``BaseEvent``: the native Runner's
17
+ ``_setup_conversation_turn`` rewrites that event's
18
+ ``interaction_id``/``turn_id``/``conversation_id`` in place (it always mints
19
+ its own ``interaction_id``), so reading these fields later off a stored
20
+ reference yields the runner's regenerated ids instead of the platform's
21
+ originals — and the platform then can't correlate, or never answers, the tool
22
+ call. Both adapters hit the same failure mode, so both snapshot at
23
+ ``invoke()`` time via ``spawn_invocation()`` below rather than re-reading the
24
+ event later.
25
+ """
26
+
27
+ import asyncio
28
+ import contextvars
29
+ from collections.abc import Awaitable, Callable
30
+ from dataclasses import dataclass
31
+
32
+ from domyn.agents.interfaces import EmitPriorityFn
33
+
34
+
35
+ @dataclass(frozen=True, slots=True)
36
+ class InvocationCtx:
37
+ """Per-invocation data needed by a platform/delegate tool round trip.
38
+
39
+ author/conversation_id/turn_id/interaction_id ride along with
40
+ emit_priority: the relay routes frames to the platform by
41
+ conversation_id and drops any frame whose value doesn't match, turn_id
42
+ is read by the transports' cross-turn replay filter, and
43
+ author/interaction_id are the correlation identity the platform matches
44
+ a TOOL_START against. Without them, TOOL_START events never reach the
45
+ platform-side runner and the tool call never completes.
46
+ """
47
+
48
+ emit_priority: EmitPriorityFn
49
+ author: str
50
+ conversation_id: str | None
51
+ turn_id: str | None
52
+ interaction_id: str | None
53
+
54
+
55
+ # Shared by every FrameworkAdapter implementation. Safe across adapter types:
56
+ # each adapter's own _runner_task (built by spawn_invocation below) sets and
57
+ # resets its own value inside its own task's context, and InvocationCtx
58
+ # carries the invocation's own emit_priority closure rather than depending on
59
+ # which adapter subclass is running — nothing reads adapter identity off it.
60
+ invocation_ctx: contextvars.ContextVar[InvocationCtx | None] = contextvars.ContextVar(
61
+ "adapter_invocation_ctx", default=None
62
+ )
63
+
64
+
65
+ def spawn_invocation(
66
+ *,
67
+ request_id: str,
68
+ conversation_id: str,
69
+ ctx: InvocationCtx,
70
+ semaphore: asyncio.Semaphore,
71
+ conversation_tasks: dict[str, asyncio.Task[None]],
72
+ in_flight: dict[str, asyncio.Task[None]],
73
+ run_body: Callable[[], Awaitable[None]],
74
+ ) -> None:
75
+ """Schedule *run_body* under the invocation bookkeeping both adapters share.
76
+
77
+ Registers the task in *conversation_tasks* (read by on_cancel) and
78
+ *in_flight* (read by close() / the busy-buffer check), sets *ctx* on the
79
+ shared ``invocation_ctx`` ContextVar for the duration of the call, and
80
+ bounds concurrency with *semaphore* — all reset/popped in a ``finally``
81
+ so a cancelled or failing *run_body* still cleans up.
82
+ """
83
+
84
+ async def _runner_task() -> None:
85
+ current = asyncio.current_task()
86
+ conversation_tasks[conversation_id] = current # type: ignore[assignment]
87
+ token = invocation_ctx.set(ctx)
88
+ try:
89
+ async with semaphore:
90
+ await run_body()
91
+ finally:
92
+ invocation_ctx.reset(token)
93
+ conversation_tasks.pop(conversation_id, None)
94
+
95
+ task = asyncio.create_task(_runner_task(), name=f"invoke:{request_id}")
96
+ in_flight[request_id] = task
97
+ task.add_done_callback(lambda _: in_flight.pop(request_id, None))
@@ -0,0 +1,407 @@
1
+ """DomynAgentAdapter — FrameworkAdapter that drives the native Domyn Runner.
2
+
3
+ WebSocket-specific code lives in the channel, not here. The adapter:
4
+
5
+ - Accepts ``(event, emit, emit_priority)`` per invocation.
6
+ - Drives ``Runner.run()`` and forwards emitted ``BaseEvent`` objects via *emit*
7
+ (best-effort) or *emit_priority* (guaranteed, used for TOOL_START and AGENT_END).
8
+ - Wires ``DelegateTool.relay`` so platform tool round-trips work:
9
+ DelegateTool.execute() → _make_tool_call() → emit_priority(TOOL_START)
10
+ → suspend on Future → on_tool_response(TOOL_END) → Future resolved → return.
11
+ - Manages in-flight task concurrency with a semaphore and a busy-buffer.
12
+ """
13
+
14
+ import asyncio
15
+ import uuid
16
+ from datetime import UTC, datetime
17
+ from typing import Any
18
+
19
+ from domyn.agents.adapters._invocation import InvocationCtx, invocation_ctx, spawn_invocation
20
+ from domyn.agents.agents import Agent
21
+ from domyn.agents.core import BaseEvent, ExecutionEventType, ToolAction
22
+ from domyn.agents.interfaces import EmitFn, EmitPriorityFn
23
+ from domyn.agents.logger import get_logger
24
+ from domyn.agents.runner import Runner
25
+ from domyn.agents.tools import DelegateTool
26
+
27
+ logger = get_logger()
28
+
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Helpers
32
+ # ---------------------------------------------------------------------------
33
+
34
+
35
+ def _collect_delegate_tools(agent: Agent) -> list[DelegateTool]:
36
+ """Walk the agent tree and collect every DelegateTool without a wrapped callable."""
37
+ tools: list[DelegateTool] = []
38
+ visited: set[str] = set()
39
+
40
+ def _walk(a: Agent) -> None:
41
+ if a.name in visited:
42
+ return
43
+ visited.add(a.name)
44
+ for tool in getattr(a, "tools", []):
45
+ if isinstance(tool, DelegateTool) and tool.wrapped is None:
46
+ tools.append(tool)
47
+ for sub in getattr(a, "sub_agents", []):
48
+ if isinstance(sub, Agent):
49
+ _walk(sub)
50
+
51
+ _walk(agent)
52
+ return tools
53
+
54
+
55
+ # ---------------------------------------------------------------------------
56
+ # DomynAgentAdapter
57
+ # ---------------------------------------------------------------------------
58
+
59
+
60
+ class DomynAgentAdapter:
61
+ """FrameworkAdapter that drives a native Domyn Agent via ``Runner.run()``.
62
+
63
+ Parameters
64
+ ----------
65
+ root:
66
+ Root agent of the agent tree to execute.
67
+ application_name:
68
+ Identifies this application in traces and conversation history.
69
+ user_id:
70
+ User identity forwarded to the Runner.
71
+ max_concurrency:
72
+ Maximum number of simultaneously active invocations.
73
+ busy_buffer:
74
+ Additional invocations queued behind the semaphore before WorkerBusy
75
+ rejection kicks in. Defaults to *max_concurrency*.
76
+ """
77
+
78
+ def __init__(
79
+ self,
80
+ root: Agent,
81
+ application_name: str = "domyn-exposed",
82
+ user_id: str = "platform",
83
+ max_concurrency: int = 8,
84
+ busy_buffer: int | None = None,
85
+ ) -> None:
86
+ self._root = root
87
+ self._application_name = application_name
88
+ self._user_id = user_id
89
+ self._max_concurrency = max_concurrency
90
+ self._busy_buffer = busy_buffer if busy_buffer is not None else max_concurrency
91
+
92
+ self._runner = Runner()
93
+ self._semaphore = asyncio.Semaphore(max_concurrency)
94
+
95
+ # In-flight task registry (keyed by request_id == event_id of AGENT_START)
96
+ self._in_flight: dict[str, asyncio.Task[None]] = {}
97
+ # Separate index by conversation_id for cancel routing
98
+ self._conversation_tasks: dict[str, asyncio.Task[None]] = {}
99
+
100
+ # Platform-tool round-trip state
101
+ self._platform_calls: dict[str, asyncio.Future[Any]] = {}
102
+
103
+ # Wire relay onto every DelegateTool in the agent tree
104
+ self._delegate_tools = _collect_delegate_tools(root)
105
+ self._delegate_tool_names = frozenset(t.tool_name for t in self._delegate_tools)
106
+ for tool in self._delegate_tools:
107
+ tool.relay = self._make_tool_call
108
+ if self._delegate_tools:
109
+ logger.info(
110
+ "DomynAgentAdapter: wired delegate tools: %s",
111
+ ", ".join(t.tool_name for t in self._delegate_tools),
112
+ )
113
+
114
+ self.events_dropped: int = 0
115
+
116
+ # ------------------------------------------------------------------
117
+ # Periodic platform-tool rediscovery
118
+ # ------------------------------------------------------------------
119
+
120
+ async def refresh_delegate_tools(
121
+ self,
122
+ api_key: str | None,
123
+ space_id: str | None,
124
+ channel_id: str | None,
125
+ base_url: str | None,
126
+ configuration_id: str | None,
127
+ attach_new_tools: bool = True,
128
+ ) -> None:
129
+ """Re-run platform tool discovery against the live agent tree.
130
+
131
+ Unlike the one-time call at startup, a failed fetch here leaves the
132
+ existing tool set untouched (``drop_on_fetch_failure=False``) — a
133
+ transient network blip must not wipe out every platform tool from a
134
+ running worker. Newly attached DelegateTool instances are wired with
135
+ this adapter's relay exactly as ``__init__`` wires the initial set.
136
+ """
137
+ from domyn.agents.integrations.domyn import populate_delegate_tool_schemas
138
+
139
+ await populate_delegate_tool_schemas(
140
+ root=self._root,
141
+ api_key=api_key,
142
+ space_id=space_id,
143
+ channel_id=channel_id,
144
+ base_url=base_url,
145
+ configuration_id=configuration_id,
146
+ attach_new_tools=attach_new_tools,
147
+ drop_on_fetch_failure=False,
148
+ )
149
+
150
+ fresh = _collect_delegate_tools(self._root)
151
+ for tool in fresh:
152
+ if tool.relay is None:
153
+ tool.relay = self._make_tool_call
154
+ self._delegate_tools = fresh
155
+ self._delegate_tool_names = frozenset(t.tool_name for t in fresh)
156
+ if fresh:
157
+ logger.info(
158
+ f"DomynAgentAdapter: refreshed delegate tools: "
159
+ f"{', '.join(t.tool_name for t in fresh)}"
160
+ )
161
+
162
+ # ------------------------------------------------------------------
163
+ # FrameworkAdapter contract
164
+ # ------------------------------------------------------------------
165
+
166
+ async def invoke(
167
+ self,
168
+ event: BaseEvent,
169
+ emit: EmitFn,
170
+ emit_priority: EmitPriorityFn,
171
+ ) -> None:
172
+ """Schedule execution of one AGENT_START event.
173
+
174
+ Returns immediately after creating the asyncio.Task.
175
+ """
176
+ request_id = event.event_id or ""
177
+ if not request_id:
178
+ logger.warning("DomynAgentAdapter.invoke: AGENT_START has no event_id; skipping")
179
+ return
180
+
181
+ if len(self._in_flight) >= self._max_concurrency + self._busy_buffer:
182
+ # event_id is per-frame unique; let BaseEvent auto-generate it. Stamping the
183
+ # inbound request's id here makes the delegating transport dedup this frame as
184
+ # a replay of the AGENT_START it already saw and drop it silently, so the turn
185
+ # dies on a read timeout instead. The correlation rides in metadata.
186
+ busy = BaseEvent(
187
+ event_type=ExecutionEventType.ERROR_OCCURRED,
188
+ author=event.author,
189
+ timestamp=datetime.now(UTC).replace(tzinfo=None),
190
+ interaction_id=event.interaction_id,
191
+ error_code="WorkerBusy",
192
+ error_message="max concurrency reached",
193
+ metadata={"request_id": request_id},
194
+ )
195
+ await emit_priority(busy)
196
+ return
197
+
198
+ conversation_id = event.conversation_id or request_id
199
+
200
+ async def _run_body() -> None:
201
+ await self._run_agent(event, request_id, conversation_id, emit, emit_priority)
202
+
203
+ spawn_invocation(
204
+ request_id=request_id,
205
+ conversation_id=conversation_id,
206
+ ctx=InvocationCtx(
207
+ emit_priority=emit_priority,
208
+ author=event.author,
209
+ conversation_id=conversation_id,
210
+ turn_id=event.turn_id,
211
+ interaction_id=event.interaction_id,
212
+ ),
213
+ semaphore=self._semaphore,
214
+ conversation_tasks=self._conversation_tasks,
215
+ in_flight=self._in_flight,
216
+ run_body=_run_body,
217
+ )
218
+
219
+ def on_tool_response(self, event: BaseEvent) -> None:
220
+ """Resolve (or reject) the Future suspended on a DelegateTool call."""
221
+ call_id = getattr(event.action, "call_id", None) if event.action else None
222
+ if call_id is None:
223
+ return
224
+ future = self._platform_calls.pop(call_id, None)
225
+ if future is None or future.done():
226
+ return
227
+ if event.event_type == ExecutionEventType.TOOL_ERROR:
228
+ future.set_exception(
229
+ RuntimeError(event.error_message or f"platform tool error ({event.error_code})")
230
+ )
231
+ else:
232
+ observation = getattr(event.action, "observation", None) if event.action else None
233
+ future.set_result(observation)
234
+
235
+ def on_cancel(self, event: BaseEvent) -> None:
236
+ """Cancel the in-flight task for the given conversation_id."""
237
+ conv_id = event.conversation_id
238
+ if not conv_id:
239
+ logger.debug("DomynAgentAdapter.on_cancel: no conversation_id — cancelling all")
240
+ for t in list(self._in_flight.values()):
241
+ t.cancel()
242
+ return
243
+ task: asyncio.Task[None] | None = self._conversation_tasks.get(conv_id)
244
+ if task is None or task.done():
245
+ logger.debug("DomynAgentAdapter.on_cancel: no in-flight task for conv=%s", conv_id)
246
+ return
247
+ logger.info("DomynAgentAdapter.on_cancel: cancelling conv=%s", conv_id)
248
+ task.cancel()
249
+
250
+ async def close(self) -> None:
251
+ """Cancel all in-flight tasks and reject pending DelegateTool Futures."""
252
+ for fut in self._platform_calls.values():
253
+ if not fut.done():
254
+ fut.set_exception(RuntimeError("DomynAgentAdapter shutting down"))
255
+ self._platform_calls.clear()
256
+ self._conversation_tasks.clear()
257
+ for task in list(self._in_flight.values()):
258
+ task.cancel()
259
+ if self._in_flight:
260
+ await asyncio.gather(*self._in_flight.values(), return_exceptions=True)
261
+
262
+ # ------------------------------------------------------------------
263
+ # Internal — invocation execution
264
+ # ------------------------------------------------------------------
265
+
266
+ async def _run_agent(
267
+ self,
268
+ agent_start: BaseEvent,
269
+ request_id: str,
270
+ conversation_id: str,
271
+ emit: EmitFn,
272
+ emit_priority: EmitPriorityFn,
273
+ ) -> None:
274
+ """Run the Runner for one invocation and forward events to the channel."""
275
+ done: BaseEvent
276
+ try:
277
+ _saw_terminal = False
278
+ async for ev in self._runner.run(
279
+ application_name=self._application_name,
280
+ user_id=self._user_id,
281
+ user_input=agent_start,
282
+ root=self._root,
283
+ conversation_id=conversation_id,
284
+ ):
285
+ # Track whether the runner itself emitted a terminal event so we
286
+ # skip the synthetic AGENT_END below.
287
+ if (
288
+ (ev.event_type == ExecutionEventType.AGENT_END and ev.author == self._root.name)
289
+ or (ev.event_type == ExecutionEventType.RESPONSE and not ev.is_partial)
290
+ or ev.event_type == ExecutionEventType.TOOL_NEEDS_FEEDBACK
291
+ ):
292
+ _saw_terminal = True
293
+
294
+ # Suppress the runner's observability TOOL_START/TOOL_END for
295
+ # DelegateTool names. _make_tool_call() runs the whole round trip
296
+ # itself under a fresh call_id: it sends its own TOOL_START, and
297
+ # the platform answers with the TOOL_END that resolves it. The
298
+ # runner's pair carries the *LLM's* tool_call id instead — an id
299
+ # the platform never issued — so forwarding them shows the relay a
300
+ # duplicate TOOL_START and then a TOOL_END for a call it cannot
301
+ # match. TOOL_ERROR is deliberately still forwarded: that one
302
+ # reports a local failure (e.g. the relay round trip itself
303
+ # failing), which is information the platform does not already have.
304
+ if (
305
+ ev.event_type in (ExecutionEventType.TOOL_START, ExecutionEventType.TOOL_END)
306
+ and getattr(ev.action, "name", None) in self._delegate_tool_names
307
+ ):
308
+ continue
309
+
310
+ # Must never be dropped: losing it strands the turn forever — the
311
+ # human never sees the approval request, and nothing else will
312
+ # ever re-prompt them. emit() is best-effort (drops when the
313
+ # channel's outbound queue is full); emit_priority() blocks
314
+ # instead, the same guarantee already given to TOOL_START/AGENT_END.
315
+ if ev.event_type == ExecutionEventType.TOOL_NEEDS_FEEDBACK:
316
+ await emit_priority(ev)
317
+ continue
318
+
319
+ await emit(ev)
320
+
321
+ if _saw_terminal:
322
+ return
323
+
324
+ done = BaseEvent(
325
+ event_type=ExecutionEventType.AGENT_END,
326
+ author=self._root.name,
327
+ timestamp=datetime.now(UTC).replace(tzinfo=None),
328
+ interaction_id=agent_start.interaction_id,
329
+ conversation_id=conversation_id,
330
+ turn_id=agent_start.turn_id,
331
+ metadata={"request_id": request_id},
332
+ )
333
+ except asyncio.CancelledError:
334
+ raise
335
+ except Exception as exc:
336
+ logger.error(
337
+ "DomynAgentAdapter: invocation failed request_id=%s: %s",
338
+ request_id,
339
+ exc,
340
+ exc_info=True,
341
+ )
342
+ done = BaseEvent(
343
+ event_type=ExecutionEventType.AGENT_END,
344
+ author=self._root.name,
345
+ timestamp=datetime.now(UTC).replace(tzinfo=None),
346
+ interaction_id=agent_start.interaction_id,
347
+ conversation_id=conversation_id,
348
+ turn_id=agent_start.turn_id,
349
+ error_code=type(exc).__name__,
350
+ error_message=str(exc),
351
+ metadata={"request_id": request_id},
352
+ )
353
+
354
+ done = done.model_copy(update={"timestamp": datetime.now(UTC).replace(tzinfo=None)})
355
+ await emit_priority(done)
356
+
357
+ # ------------------------------------------------------------------
358
+ # Internal — DelegateTool round-trip
359
+ # ------------------------------------------------------------------
360
+
361
+ async def _make_tool_call(self, name: str, kwargs: dict[str, Any]) -> Any:
362
+ """Send TOOL_START to the relay and suspend until TOOL_END / TOOL_ERROR.
363
+
364
+ Called by ``DelegateTool.execute()`` via ``tool.relay``. Correlation IDs
365
+ are read from the shared ``invocation_ctx`` ContextVar set by
366
+ ``invoke()`` via ``spawn_invocation()``, not from
367
+ ``asyncio.current_task()``: ``Runner._merge_with_injections`` drives
368
+ every step of the turn (including the step that reaches this
369
+ DelegateTool) in a fresh ``asyncio.Task`` via ``asyncio.ensure_future``,
370
+ so the task executing here is never the one ``invoke()`` created. The
371
+ ContextVar is still found because a ``contextvars.Context`` is copied
372
+ into every child task spawned from a task carrying it, and concurrent
373
+ invocations each get their own copy — see ``InvocationCtx``.
374
+ """
375
+ ctx = invocation_ctx.get()
376
+
377
+ if ctx is None:
378
+ raise RuntimeError(
379
+ "DomynAgentAdapter._make_tool_call: no invocation context for current task — "
380
+ "cannot send TOOL_START. Is the DelegateTool being called outside of invoke()?"
381
+ )
382
+
383
+ call_id = str(uuid.uuid4())
384
+ tool_start = BaseEvent(
385
+ event_type=ExecutionEventType.TOOL_START,
386
+ author=ctx.author,
387
+ timestamp=datetime.now(UTC).replace(tzinfo=None),
388
+ conversation_id=ctx.conversation_id,
389
+ interaction_id=ctx.interaction_id,
390
+ turn_id=ctx.turn_id,
391
+ action=ToolAction(name=name, parameters=kwargs, call_id=call_id),
392
+ )
393
+
394
+ loop = asyncio.get_running_loop()
395
+ future: asyncio.Future[Any] = loop.create_future()
396
+ self._platform_calls[call_id] = future
397
+
398
+ try:
399
+ await ctx.emit_priority(tool_start)
400
+ except Exception:
401
+ self._platform_calls.pop(call_id, None)
402
+ raise
403
+
404
+ try:
405
+ return await future
406
+ finally:
407
+ self._platform_calls.pop(call_id, None)