alita-sdk 0.3.379__py3-none-any.whl → 0.3.627__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 (278) hide show
  1. alita_sdk/cli/__init__.py +10 -0
  2. alita_sdk/cli/__main__.py +17 -0
  3. alita_sdk/cli/agent/__init__.py +5 -0
  4. alita_sdk/cli/agent/default.py +258 -0
  5. alita_sdk/cli/agent_executor.py +156 -0
  6. alita_sdk/cli/agent_loader.py +245 -0
  7. alita_sdk/cli/agent_ui.py +228 -0
  8. alita_sdk/cli/agents.py +3113 -0
  9. alita_sdk/cli/callbacks.py +647 -0
  10. alita_sdk/cli/cli.py +168 -0
  11. alita_sdk/cli/config.py +306 -0
  12. alita_sdk/cli/context/__init__.py +30 -0
  13. alita_sdk/cli/context/cleanup.py +198 -0
  14. alita_sdk/cli/context/manager.py +731 -0
  15. alita_sdk/cli/context/message.py +285 -0
  16. alita_sdk/cli/context/strategies.py +289 -0
  17. alita_sdk/cli/context/token_estimation.py +127 -0
  18. alita_sdk/cli/formatting.py +182 -0
  19. alita_sdk/cli/input_handler.py +419 -0
  20. alita_sdk/cli/inventory.py +1073 -0
  21. alita_sdk/cli/mcp_loader.py +315 -0
  22. alita_sdk/cli/testcases/__init__.py +94 -0
  23. alita_sdk/cli/testcases/data_generation.py +119 -0
  24. alita_sdk/cli/testcases/discovery.py +96 -0
  25. alita_sdk/cli/testcases/executor.py +84 -0
  26. alita_sdk/cli/testcases/logger.py +85 -0
  27. alita_sdk/cli/testcases/parser.py +172 -0
  28. alita_sdk/cli/testcases/prompts.py +91 -0
  29. alita_sdk/cli/testcases/reporting.py +125 -0
  30. alita_sdk/cli/testcases/setup.py +108 -0
  31. alita_sdk/cli/testcases/test_runner.py +282 -0
  32. alita_sdk/cli/testcases/utils.py +39 -0
  33. alita_sdk/cli/testcases/validation.py +90 -0
  34. alita_sdk/cli/testcases/workflow.py +196 -0
  35. alita_sdk/cli/toolkit.py +327 -0
  36. alita_sdk/cli/toolkit_loader.py +85 -0
  37. alita_sdk/cli/tools/__init__.py +43 -0
  38. alita_sdk/cli/tools/approval.py +224 -0
  39. alita_sdk/cli/tools/filesystem.py +1751 -0
  40. alita_sdk/cli/tools/planning.py +389 -0
  41. alita_sdk/cli/tools/terminal.py +414 -0
  42. alita_sdk/community/__init__.py +72 -12
  43. alita_sdk/community/inventory/__init__.py +236 -0
  44. alita_sdk/community/inventory/config.py +257 -0
  45. alita_sdk/community/inventory/enrichment.py +2137 -0
  46. alita_sdk/community/inventory/extractors.py +1469 -0
  47. alita_sdk/community/inventory/ingestion.py +3172 -0
  48. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  49. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  50. alita_sdk/community/inventory/parsers/base.py +295 -0
  51. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  52. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  53. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  54. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  55. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  56. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  57. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  58. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  59. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  60. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  61. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  62. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  63. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  64. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  65. alita_sdk/community/inventory/patterns/loader.py +348 -0
  66. alita_sdk/community/inventory/patterns/registry.py +198 -0
  67. alita_sdk/community/inventory/presets.py +535 -0
  68. alita_sdk/community/inventory/retrieval.py +1403 -0
  69. alita_sdk/community/inventory/toolkit.py +173 -0
  70. alita_sdk/community/inventory/toolkit_utils.py +176 -0
  71. alita_sdk/community/inventory/visualize.py +1370 -0
  72. alita_sdk/configurations/__init__.py +1 -1
  73. alita_sdk/configurations/ado.py +141 -20
  74. alita_sdk/configurations/bitbucket.py +94 -2
  75. alita_sdk/configurations/confluence.py +130 -1
  76. alita_sdk/configurations/figma.py +76 -0
  77. alita_sdk/configurations/gitlab.py +91 -0
  78. alita_sdk/configurations/jira.py +103 -0
  79. alita_sdk/configurations/openapi.py +329 -0
  80. alita_sdk/configurations/qtest.py +72 -1
  81. alita_sdk/configurations/report_portal.py +96 -0
  82. alita_sdk/configurations/sharepoint.py +148 -0
  83. alita_sdk/configurations/testio.py +83 -0
  84. alita_sdk/configurations/testrail.py +88 -0
  85. alita_sdk/configurations/xray.py +93 -0
  86. alita_sdk/configurations/zephyr_enterprise.py +93 -0
  87. alita_sdk/configurations/zephyr_essential.py +75 -0
  88. alita_sdk/runtime/clients/artifact.py +3 -3
  89. alita_sdk/runtime/clients/client.py +388 -46
  90. alita_sdk/runtime/clients/mcp_discovery.py +342 -0
  91. alita_sdk/runtime/clients/mcp_manager.py +262 -0
  92. alita_sdk/runtime/clients/sandbox_client.py +8 -21
  93. alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
  94. alita_sdk/runtime/langchain/assistant.py +157 -39
  95. alita_sdk/runtime/langchain/constants.py +647 -1
  96. alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
  97. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
  98. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
  99. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -4
  100. alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
  101. alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
  102. alita_sdk/runtime/langchain/document_loaders/constants.py +40 -19
  103. alita_sdk/runtime/langchain/langraph_agent.py +405 -84
  104. alita_sdk/runtime/langchain/utils.py +106 -7
  105. alita_sdk/runtime/llms/preloaded.py +2 -6
  106. alita_sdk/runtime/models/mcp_models.py +61 -0
  107. alita_sdk/runtime/skills/__init__.py +91 -0
  108. alita_sdk/runtime/skills/callbacks.py +498 -0
  109. alita_sdk/runtime/skills/discovery.py +540 -0
  110. alita_sdk/runtime/skills/executor.py +610 -0
  111. alita_sdk/runtime/skills/input_builder.py +371 -0
  112. alita_sdk/runtime/skills/models.py +330 -0
  113. alita_sdk/runtime/skills/registry.py +355 -0
  114. alita_sdk/runtime/skills/skill_runner.py +330 -0
  115. alita_sdk/runtime/toolkits/__init__.py +31 -0
  116. alita_sdk/runtime/toolkits/application.py +29 -10
  117. alita_sdk/runtime/toolkits/artifact.py +20 -11
  118. alita_sdk/runtime/toolkits/datasource.py +13 -6
  119. alita_sdk/runtime/toolkits/mcp.py +783 -0
  120. alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
  121. alita_sdk/runtime/toolkits/planning.py +178 -0
  122. alita_sdk/runtime/toolkits/skill_router.py +238 -0
  123. alita_sdk/runtime/toolkits/subgraph.py +251 -6
  124. alita_sdk/runtime/toolkits/tools.py +356 -69
  125. alita_sdk/runtime/toolkits/vectorstore.py +11 -5
  126. alita_sdk/runtime/tools/__init__.py +10 -3
  127. alita_sdk/runtime/tools/application.py +27 -6
  128. alita_sdk/runtime/tools/artifact.py +511 -28
  129. alita_sdk/runtime/tools/data_analysis.py +183 -0
  130. alita_sdk/runtime/tools/function.py +67 -35
  131. alita_sdk/runtime/tools/graph.py +10 -4
  132. alita_sdk/runtime/tools/image_generation.py +148 -46
  133. alita_sdk/runtime/tools/llm.py +1003 -128
  134. alita_sdk/runtime/tools/loop.py +3 -1
  135. alita_sdk/runtime/tools/loop_output.py +3 -1
  136. alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
  137. alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
  138. alita_sdk/runtime/tools/mcp_server_tool.py +8 -5
  139. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  140. alita_sdk/runtime/tools/planning/models.py +246 -0
  141. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  142. alita_sdk/runtime/tools/router.py +2 -4
  143. alita_sdk/runtime/tools/sandbox.py +65 -48
  144. alita_sdk/runtime/tools/skill_router.py +776 -0
  145. alita_sdk/runtime/tools/tool.py +3 -1
  146. alita_sdk/runtime/tools/vectorstore.py +9 -3
  147. alita_sdk/runtime/tools/vectorstore_base.py +70 -14
  148. alita_sdk/runtime/utils/AlitaCallback.py +137 -21
  149. alita_sdk/runtime/utils/constants.py +5 -1
  150. alita_sdk/runtime/utils/mcp_client.py +492 -0
  151. alita_sdk/runtime/utils/mcp_oauth.py +361 -0
  152. alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
  153. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  154. alita_sdk/runtime/utils/serialization.py +155 -0
  155. alita_sdk/runtime/utils/streamlit.py +40 -13
  156. alita_sdk/runtime/utils/toolkit_utils.py +30 -9
  157. alita_sdk/runtime/utils/utils.py +36 -0
  158. alita_sdk/tools/__init__.py +134 -35
  159. alita_sdk/tools/ado/repos/__init__.py +51 -32
  160. alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
  161. alita_sdk/tools/ado/test_plan/__init__.py +25 -9
  162. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
  163. alita_sdk/tools/ado/utils.py +1 -18
  164. alita_sdk/tools/ado/wiki/__init__.py +25 -12
  165. alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
  166. alita_sdk/tools/ado/work_item/__init__.py +26 -13
  167. alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
  168. alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
  169. alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
  170. alita_sdk/tools/aws/delta_lake/tool.py +5 -1
  171. alita_sdk/tools/azure_ai/search/__init__.py +11 -8
  172. alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
  173. alita_sdk/tools/base/tool.py +5 -1
  174. alita_sdk/tools/base_indexer_toolkit.py +271 -84
  175. alita_sdk/tools/bitbucket/__init__.py +17 -11
  176. alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
  177. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
  178. alita_sdk/tools/browser/__init__.py +5 -4
  179. alita_sdk/tools/carrier/__init__.py +5 -6
  180. alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
  181. alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
  182. alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
  183. alita_sdk/tools/chunkers/__init__.py +3 -1
  184. alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
  185. alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
  186. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  187. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  188. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  189. alita_sdk/tools/cloud/aws/__init__.py +10 -7
  190. alita_sdk/tools/cloud/azure/__init__.py +10 -7
  191. alita_sdk/tools/cloud/gcp/__init__.py +10 -7
  192. alita_sdk/tools/cloud/k8s/__init__.py +10 -7
  193. alita_sdk/tools/code/linter/__init__.py +10 -8
  194. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  195. alita_sdk/tools/code/sonar/__init__.py +11 -8
  196. alita_sdk/tools/code_indexer_toolkit.py +82 -22
  197. alita_sdk/tools/confluence/__init__.py +22 -16
  198. alita_sdk/tools/confluence/api_wrapper.py +107 -30
  199. alita_sdk/tools/confluence/loader.py +14 -2
  200. alita_sdk/tools/custom_open_api/__init__.py +12 -5
  201. alita_sdk/tools/elastic/__init__.py +11 -8
  202. alita_sdk/tools/elitea_base.py +493 -30
  203. alita_sdk/tools/figma/__init__.py +58 -11
  204. alita_sdk/tools/figma/api_wrapper.py +1235 -143
  205. alita_sdk/tools/figma/figma_client.py +73 -0
  206. alita_sdk/tools/figma/toon_tools.py +2748 -0
  207. alita_sdk/tools/github/__init__.py +14 -15
  208. alita_sdk/tools/github/github_client.py +224 -100
  209. alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
  210. alita_sdk/tools/github/schemas.py +14 -5
  211. alita_sdk/tools/github/tool.py +5 -1
  212. alita_sdk/tools/github/tool_prompts.py +9 -22
  213. alita_sdk/tools/gitlab/__init__.py +16 -11
  214. alita_sdk/tools/gitlab/api_wrapper.py +218 -48
  215. alita_sdk/tools/gitlab_org/__init__.py +10 -9
  216. alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
  217. alita_sdk/tools/google/bigquery/__init__.py +13 -12
  218. alita_sdk/tools/google/bigquery/tool.py +5 -1
  219. alita_sdk/tools/google_places/__init__.py +11 -8
  220. alita_sdk/tools/google_places/api_wrapper.py +1 -1
  221. alita_sdk/tools/jira/__init__.py +17 -10
  222. alita_sdk/tools/jira/api_wrapper.py +92 -41
  223. alita_sdk/tools/keycloak/__init__.py +11 -8
  224. alita_sdk/tools/localgit/__init__.py +9 -3
  225. alita_sdk/tools/localgit/local_git.py +62 -54
  226. alita_sdk/tools/localgit/tool.py +5 -1
  227. alita_sdk/tools/memory/__init__.py +12 -4
  228. alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
  229. alita_sdk/tools/ocr/__init__.py +11 -8
  230. alita_sdk/tools/openapi/__init__.py +491 -106
  231. alita_sdk/tools/openapi/api_wrapper.py +1368 -0
  232. alita_sdk/tools/openapi/tool.py +20 -0
  233. alita_sdk/tools/pandas/__init__.py +20 -12
  234. alita_sdk/tools/pandas/api_wrapper.py +38 -25
  235. alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
  236. alita_sdk/tools/postman/__init__.py +10 -9
  237. alita_sdk/tools/pptx/__init__.py +11 -10
  238. alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
  239. alita_sdk/tools/qtest/__init__.py +31 -11
  240. alita_sdk/tools/qtest/api_wrapper.py +2135 -86
  241. alita_sdk/tools/rally/__init__.py +10 -9
  242. alita_sdk/tools/rally/api_wrapper.py +1 -1
  243. alita_sdk/tools/report_portal/__init__.py +12 -8
  244. alita_sdk/tools/salesforce/__init__.py +10 -8
  245. alita_sdk/tools/servicenow/__init__.py +17 -15
  246. alita_sdk/tools/servicenow/api_wrapper.py +1 -1
  247. alita_sdk/tools/sharepoint/__init__.py +10 -7
  248. alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
  249. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  250. alita_sdk/tools/sharepoint/utils.py +8 -2
  251. alita_sdk/tools/slack/__init__.py +10 -7
  252. alita_sdk/tools/slack/api_wrapper.py +2 -2
  253. alita_sdk/tools/sql/__init__.py +12 -9
  254. alita_sdk/tools/testio/__init__.py +10 -7
  255. alita_sdk/tools/testrail/__init__.py +11 -10
  256. alita_sdk/tools/testrail/api_wrapper.py +1 -1
  257. alita_sdk/tools/utils/__init__.py +9 -4
  258. alita_sdk/tools/utils/content_parser.py +103 -18
  259. alita_sdk/tools/utils/text_operations.py +410 -0
  260. alita_sdk/tools/utils/tool_prompts.py +79 -0
  261. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +30 -13
  262. alita_sdk/tools/xray/__init__.py +13 -9
  263. alita_sdk/tools/yagmail/__init__.py +9 -3
  264. alita_sdk/tools/zephyr/__init__.py +10 -7
  265. alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
  266. alita_sdk/tools/zephyr_essential/__init__.py +10 -7
  267. alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
  268. alita_sdk/tools/zephyr_essential/client.py +2 -2
  269. alita_sdk/tools/zephyr_scale/__init__.py +11 -8
  270. alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
  271. alita_sdk/tools/zephyr_squad/__init__.py +10 -7
  272. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
  273. alita_sdk-0.3.627.dist-info/RECORD +468 -0
  274. alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
  275. alita_sdk-0.3.379.dist-info/RECORD +0 -360
  276. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
  277. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
  278. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from typing import Optional
2
3
 
3
4
  from langchain_core.tools import ToolException
4
5
  from langgraph.store.base import BaseStore
@@ -8,15 +9,23 @@ from alita_sdk.tools import get_tools as alita_tools
8
9
  from .application import ApplicationToolkit
9
10
  from .artifact import ArtifactToolkit
10
11
  from .datasource import DatasourcesToolkit
12
+ from .planning import PlanningToolkit
11
13
  from .prompt import PromptToolkit
12
14
  from .subgraph import SubgraphToolkit
13
15
  from .vectorstore import VectorStoreToolkit
16
+ from .mcp import McpToolkit
17
+ from .mcp_config import McpConfigToolkit, get_mcp_config_toolkit_schemas
18
+ from .skill_router import SkillRouterToolkit
14
19
  from ..tools.mcp_server_tool import McpServerTool
15
20
  from ..tools.sandbox import SandboxToolkit
21
+ from ..tools.image_generation import ImageGenerationToolkit
22
+ from ..tools.data_analysis import DataAnalysisToolkit
16
23
  # Import community tools
17
24
  from ...community import get_toolkits as community_toolkits, get_tools as community_tools
18
25
  from ...tools.memory import MemoryToolkit
19
- from ...tools.utils import TOOLKIT_SPLITTER
26
+ from ..utils.mcp_oauth import canonical_resource, McpAuthorizationRequired
27
+ from ...tools.utils import clean_string
28
+ from alita_sdk.tools import _inject_toolkit_id
20
29
 
21
30
  logger = logging.getLogger(__name__)
22
31
 
@@ -25,82 +34,344 @@ def get_toolkits():
25
34
  core_toolkits = [
26
35
  ArtifactToolkit.toolkit_config_schema(),
27
36
  MemoryToolkit.toolkit_config_schema(),
37
+ PlanningToolkit.toolkit_config_schema(),
28
38
  VectorStoreToolkit.toolkit_config_schema(),
29
- SandboxToolkit.toolkit_config_schema()
39
+ SandboxToolkit.toolkit_config_schema(),
40
+ ImageGenerationToolkit.toolkit_config_schema(),
41
+ DataAnalysisToolkit.toolkit_config_schema(),
42
+ McpToolkit.toolkit_config_schema(),
43
+ McpConfigToolkit.toolkit_config_schema(),
44
+ SkillRouterToolkit.toolkit_config_schema()
30
45
  ]
31
46
 
32
- return core_toolkits + community_toolkits() + alita_toolkits()
47
+ # Add configured MCP servers (stdio and http) as available toolkits
48
+ mcp_config_toolkits = get_mcp_config_toolkit_schemas()
33
49
 
50
+ return core_toolkits + mcp_config_toolkits + community_toolkits() + alita_toolkits()
51
+
52
+
53
+ def get_tools(tools_list: list, alita_client=None, llm=None, memory_store: BaseStore = None, debug_mode: Optional[bool] = False, mcp_tokens: Optional[dict] = None, conversation_id: Optional[str] = None, ignored_mcp_servers: Optional[list] = None) -> list:
54
+ # Sanitize tools_list to handle corrupted tool configurations
55
+ sanitized_tools = []
56
+ for tool in tools_list:
57
+ if isinstance(tool, dict):
58
+ # Check for corrupted structure where 'type' and 'name' contain the full tool config
59
+ if 'type' in tool and isinstance(tool['type'], dict):
60
+ # This is a corrupted tool - use the inner dict instead
61
+ logger.warning(f"Detected corrupted tool configuration (type=dict), fixing: {tool}")
62
+ actual_tool = tool['type'] # or tool['name'], they should be the same
63
+ sanitized_tools.append(actual_tool)
64
+ elif 'name' in tool and isinstance(tool['name'], dict):
65
+ # Another corruption pattern where name contains the full config
66
+ logger.warning(f"Detected corrupted tool configuration (name=dict), fixing: {tool}")
67
+ actual_tool = tool['name']
68
+ sanitized_tools.append(actual_tool)
69
+ elif 'type' in tool and isinstance(tool['type'], str):
70
+ # Valid tool configuration
71
+ sanitized_tools.append(tool)
72
+ else:
73
+ # Skip invalid/corrupted tools that can't be fixed
74
+ logger.warning(f"Skipping invalid tool configuration: {tool}")
75
+ else:
76
+ logger.warning(f"Skipping non-dict tool: {tool}")
77
+ # Skip non-dict tools
34
78
 
35
- def get_tools(tools_list: list, alita_client, llm, memory_store: BaseStore = None) -> list:
36
79
  prompts = []
37
80
  tools = []
81
+ unhandled_tools = [] # Track tools not handled by main processing
38
82
 
39
- for tool in tools_list:
40
- if tool['type'] == 'datasource':
41
- tools.extend(DatasourcesToolkit.get_toolkit(
42
- alita_client,
43
- datasource_ids=[int(tool['settings']['datasource_id'])],
44
- selected_tools=tool['settings']['selected_tools'],
45
- toolkit_name=tool.get('toolkit_name', '') or tool.get('name', '')
46
- ).get_tools())
47
- elif tool['type'] == 'application' and tool.get('agent_type', '') != 'pipeline' :
48
- tools.extend(ApplicationToolkit.get_toolkit(
49
- alita_client,
50
- application_id=int(tool['settings']['application_id']),
51
- application_version_id=int(tool['settings']['application_version_id']),
52
- selected_tools=[]
53
- ).get_tools())
54
- elif tool['type'] == 'application' and tool.get('agent_type', '') == 'pipeline':
55
- # static get_toolkit returns a list of CompiledStateGraph stubs
56
- tools.extend(SubgraphToolkit.get_toolkit(
57
- alita_client,
58
- application_id=int(tool['settings']['application_id']),
59
- application_version_id=int(tool['settings']['application_version_id']),
60
- app_api_key=alita_client.auth_token,
61
- selected_tools=[],
62
- llm=llm
63
- ))
64
- elif tool['type'] == 'memory':
65
- tools += MemoryToolkit.get_toolkit(
66
- namespace=tool['settings'].get('namespace', str(tool['id'])),
67
- pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
68
- store=memory_store,
69
- ).get_tools()
70
- # TODO: update configuration of internal tools
71
- elif tool['type'] == 'internal_tool':
72
- if tool['name'] == 'pyodide':
73
- tools += SandboxToolkit.get_toolkit(
74
- stateful=False,
75
- allow_net=True,
83
+ for tool in sanitized_tools:
84
+ # Flag to track if this tool was processed by the main loop
85
+ # Used to prevent double processing by fallback systems
86
+ tool_handled = False
87
+ try:
88
+ if tool['type'] == 'datasource':
89
+ tool_handled = True
90
+ tools.extend(DatasourcesToolkit.get_toolkit(
91
+ alita_client,
92
+ datasource_ids=[int(tool['settings']['datasource_id'])],
93
+ selected_tools=tool['settings']['selected_tools'],
94
+ toolkit_name=tool.get('toolkit_name', '') or tool.get('name', '')
95
+ ).get_tools())
96
+ elif tool['type'] == 'application':
97
+ tool_handled = True
98
+ # Check if this is a pipeline to enable PrinterNode filtering
99
+ is_pipeline_subgraph = tool.get('agent_type', '') == 'pipeline'
100
+
101
+ tools.extend(ApplicationToolkit.get_toolkit(
102
+ alita_client,
103
+ application_id=int(tool['settings']['application_id']),
104
+ application_version_id=int(tool['settings']['application_version_id']),
105
+ selected_tools=[],
106
+ ignored_mcp_servers=ignored_mcp_servers,
107
+ is_subgraph=is_pipeline_subgraph, # Pass is_subgraph for pipelines
108
+ mcp_tokens=mcp_tokens
109
+ ).get_tools())
110
+ # TODO: deprecate next release (1/15/2026)
111
+ # if is_pipeline_subgraph:
112
+ # # static get_toolkit returns a list of CompiledStateGraph stubs
113
+ # # Pass is_subgraph=True to enable PrinterNode filtering
114
+ # logger.info(f"Processing pipeline as subgraph, will filter PrinterNodes")
115
+ # tools.extend(SubgraphToolkit.get_toolkit(
116
+ # alita_client,
117
+ # application_id=int(tool['settings']['application_id']),
118
+ # application_version_id=int(tool['settings']['application_version_id']),
119
+ # app_api_key=alita_client.auth_token,
120
+ # selected_tools=[],
121
+ # llm=llm,
122
+ # is_subgraph=True # Enable PrinterNode filtering for pipelines used as subgraphs
123
+ # ))
124
+ elif tool['type'] == 'memory':
125
+ tool_handled = True
126
+ tools += MemoryToolkit.get_toolkit(
127
+ namespace=tool['settings'].get('namespace', str(tool['id'])),
128
+ pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
129
+ store=memory_store,
76
130
  ).get_tools()
77
- elif tool['type'] == 'artifact':
78
- tools.extend(ArtifactToolkit.get_toolkit(
79
- client=alita_client,
80
- bucket=tool['settings']['bucket'],
81
- toolkit_name=tool.get('toolkit_name', ''),
82
- selected_tools=tool['settings'].get('selected_tools', []),
83
- llm=llm,
84
- # indexer settings
85
- pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
86
- embedding_model=tool['settings'].get('embedding_model'),
87
- collection_name=f"{tool.get('toolkit_name')}",
88
- ).get_tools())
89
- elif tool['type'] == 'vectorstore':
90
- tools.extend(VectorStoreToolkit.get_toolkit(
91
- llm=llm,
92
- toolkit_name=tool.get('toolkit_name', ''),
93
- **tool['settings']).get_tools())
94
-
131
+ # TODO: update configuration of internal tools
132
+ elif tool['type'] == 'internal_tool':
133
+ tool_handled = True
134
+ if tool['name'] == 'pyodide':
135
+ tools += SandboxToolkit.get_toolkit(
136
+ stateful=False,
137
+ allow_net=True,
138
+ alita_client=alita_client,
139
+ ).get_tools()
140
+ elif tool['name'] == 'image_generation':
141
+ if alita_client and alita_client.model_image_generation:
142
+ tools += ImageGenerationToolkit.get_toolkit(
143
+ client=alita_client,
144
+ ).get_tools()
145
+ else:
146
+ logger.warning("Image generation internal tool requested "
147
+ "but no image generation model configured")
148
+ elif tool['name'] == 'planner':
149
+ tools += PlanningToolkit.get_toolkit(
150
+ pgvector_configuration=tool.get('settings', {}).get('pgvector_configuration'),
151
+ conversation_id=conversation_id,
152
+ ).get_tools()
153
+ elif tool['name'] == 'data_analysis':
154
+ # Data Analysis internal tool - uses conversation attachment bucket
155
+ settings = tool.get('settings', {})
156
+ bucket_name = settings.get('bucket_name')
157
+ if bucket_name:
158
+ tools += DataAnalysisToolkit.get_toolkit(
159
+ alita_client=alita_client,
160
+ llm=llm,
161
+ bucket_name=bucket_name,
162
+ toolkit_name="Data Analyst",
163
+ ).get_tools()
164
+ else:
165
+ logger.warning("Data Analysis internal tool requested "
166
+ "but no bucket_name provided in settings")
167
+ elif tool['type'] == 'artifact':
168
+ tool_handled = True
169
+ toolkit_tools = ArtifactToolkit.get_toolkit(
170
+ client=alita_client,
171
+ bucket=tool['settings']['bucket'],
172
+ toolkit_name=tool.get('toolkit_name', ''),
173
+ selected_tools=tool['settings'].get('selected_tools', []),
174
+ llm=llm,
175
+ # indexer settings
176
+ pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
177
+ embedding_model=tool['settings'].get('embedding_model'),
178
+ collection_name=f"{tool.get('toolkit_name')}",
179
+ collection_schema=str(tool['settings'].get('id', tool.get('id', ''))),
180
+ ).get_tools()
181
+ # Inject toolkit_id for artifact tools as well
182
+ # Pass settings as the tool config since that's where the id field is
183
+ _inject_toolkit_id(tool['settings'], toolkit_tools)
184
+ tools.extend(toolkit_tools)
185
+
186
+ elif tool['type'] == 'vectorstore':
187
+ tool_handled = True
188
+ tools.extend(VectorStoreToolkit.get_toolkit(
189
+ llm=llm,
190
+ toolkit_name=tool.get('toolkit_name', ''),
191
+ **tool['settings']).get_tools())
192
+ elif tool['type'] == 'planning':
193
+ tool_handled = True
194
+ # Planning toolkit for multi-step task tracking
195
+ settings = tool.get('settings', {})
196
+
197
+ # Check if local mode is enabled (uses filesystem storage, ignores pgvector)
198
+ use_local = settings.get('local', False)
199
+
200
+ if use_local:
201
+ # Local mode - use filesystem storage
202
+ logger.info("Planning toolkit using local filesystem storage (local=true)")
203
+ pgvector_config = {}
204
+ else:
205
+ # Check if explicit connection_string is provided in pgvector_configuration
206
+ explicit_pgvector_config = settings.get('pgvector_configuration', {})
207
+ explicit_connstr = explicit_pgvector_config.get('connection_string') if explicit_pgvector_config else None
208
+
209
+ if explicit_connstr:
210
+ # Use explicitly provided connection string (overrides project secrets)
211
+ logger.info("Using explicit connection_string for planning toolkit")
212
+ pgvector_config = explicit_pgvector_config
213
+ else:
214
+ # Try to fetch pgvector_project_connstr from project secrets
215
+ pgvector_connstr = None
216
+ if alita_client:
217
+ try:
218
+ pgvector_connstr = alita_client.unsecret('pgvector_project_connstr')
219
+ if pgvector_connstr:
220
+ logger.info("Using pgvector_project_connstr for planning toolkit")
221
+ except Exception as e:
222
+ logger.debug(f"pgvector_project_connstr not available: {e}")
223
+
224
+ pgvector_config = {'connection_string': pgvector_connstr} if pgvector_connstr else {}
225
+
226
+ tools.extend(PlanningToolkit.get_toolkit(
227
+ toolkit_name=tool.get('toolkit_name', ''),
228
+ selected_tools=settings.get('selected_tools', []),
229
+ pgvector_configuration=pgvector_config,
230
+ conversation_id=conversation_id or settings.get('conversation_id'),
231
+ ).get_tools())
232
+ elif tool['type'] == 'mcp':
233
+ tool_handled = True
234
+ # remote mcp tool initialization with token injection
235
+ settings = dict(tool['settings'])
236
+ url = settings.get('url')
237
+
238
+ # Check if this MCP server should be ignored (user chose to continue without auth)
239
+ if ignored_mcp_servers and url:
240
+ canonical_url = canonical_resource(url)
241
+ if canonical_url in ignored_mcp_servers or url in ignored_mcp_servers:
242
+ logger.info(f"[MCP Auth] Skipping ignored MCP server: {url}")
243
+ continue
244
+
245
+ headers = settings.get('headers')
246
+ token_data = None
247
+ session_id = None
248
+ if mcp_tokens and url:
249
+ canonical_url = canonical_resource(url)
250
+ logger.info(f"[MCP Auth] Looking for token for URL: {url}")
251
+ logger.info(f"[MCP Auth] Canonical URL: {canonical_url}")
252
+ logger.info(f"[MCP Auth] Available tokens: {list(mcp_tokens.keys())}")
253
+ token_data = mcp_tokens.get(canonical_url)
254
+ if token_data:
255
+ logger.info(f"[MCP Auth] Found token data for {canonical_url}")
256
+ # Handle both old format (string) and new format (dict with access_token and session_id)
257
+ if isinstance(token_data, dict):
258
+ access_token = token_data.get('access_token')
259
+ session_id = token_data.get('session_id')
260
+ logger.info(f"[MCP Auth] Token data: access_token={'present' if access_token else 'missing'}, session_id={session_id or 'none'}")
261
+ else:
262
+ # Backward compatibility: treat as plain token string
263
+ access_token = token_data
264
+ logger.info(f"[MCP Auth] Using legacy token format (string)")
265
+ else:
266
+ access_token = None
267
+ logger.warning(f"[MCP Auth] No token found for {canonical_url}")
268
+ else:
269
+ access_token = None
270
+
271
+ if access_token:
272
+ merged_headers = dict(headers) if headers else {}
273
+ merged_headers.setdefault('Authorization', f'Bearer {access_token}')
274
+ settings['headers'] = merged_headers
275
+ logger.info(f"[MCP Auth] Added Authorization header for {url}")
276
+
277
+ # Pass session_id to MCP toolkit if available
278
+ if session_id:
279
+ settings['session_id'] = session_id
280
+ logger.info(f"[MCP Auth] Passing session_id to toolkit: {session_id}")
281
+ tools.extend(McpToolkit.get_toolkit(
282
+ toolkit_name=tool.get('toolkit_name', ''),
283
+ client=alita_client,
284
+ **settings).get_tools())
285
+ elif tool['type'] == 'skill_router':
286
+ tool_handled = True
287
+ # Skills Registry Router Toolkit
288
+ logger.info(f"Processing skill_router toolkit: {tool}")
289
+ try:
290
+ settings = tool.get('settings', {})
291
+ toolkit_name = tool.get('toolkit_name', '')
292
+ selected_tools = settings.get('selected_tools', [])
293
+
294
+ toolkit_tools = SkillRouterToolkit.get_toolkit(
295
+ client=alita_client,
296
+ llm=llm,
297
+ toolkit_name=toolkit_name,
298
+ selected_tools=selected_tools,
299
+ **settings
300
+ ).get_tools()
301
+
302
+ tools.extend(toolkit_tools)
303
+ logger.info(f"✅ Successfully added {len(toolkit_tools)} tools from SkillRouterToolkit")
304
+ except Exception as e:
305
+ logger.error(f"❌ Failed to initialize SkillRouterToolkit: {e}")
306
+ raise
307
+ elif tool['type'] == 'mcp_config' or tool['type'].startswith('mcp_'):
308
+ tool_handled = True
309
+ # MCP Config toolkit - pre-configured MCP servers (stdio or http)
310
+ # Handle both explicit 'mcp_config' type and dynamic names like 'mcp_playwright'
311
+ logger.info(f"Processing mcp_config toolkit: {tool}")
312
+ try:
313
+ settings = tool.get('settings', {})
314
+
315
+ # Server name can come from settings or be extracted from type name
316
+ server_name = settings.get('server_name')
317
+ if not server_name and tool['type'].startswith('mcp_') and tool['type'] != 'mcp_config':
318
+ # Extract server name from type (e.g., 'mcp_playwright' -> 'playwright')
319
+ server_name = tool['type'][4:] # Remove 'mcp_' prefix
320
+
321
+ if not server_name:
322
+ logger.error(f"❌ No server_name found for mcp_config toolkit: {tool}")
323
+ continue
324
+
325
+ toolkit_name = tool.get('toolkit_name', '') or server_name
326
+ selected_tools = settings.get('selected_tools', [])
327
+ excluded_tools = settings.get('excluded_tools', [])
328
+
329
+ # Get server config (may be in settings or from global config)
330
+ server_config = settings.get('server_config')
331
+
332
+ toolkit_tools = McpConfigToolkit.get_toolkit(
333
+ server_name=server_name,
334
+ server_config=server_config,
335
+ user_config=settings,
336
+ selected_tools=selected_tools if selected_tools else None,
337
+ excluded_tools=excluded_tools if excluded_tools else None,
338
+ toolkit_name=toolkit_name,
339
+ client=alita_client,
340
+ ).get_tools()
341
+
342
+ tools.extend(toolkit_tools)
343
+ logger.info(f"✅ Successfully added {len(toolkit_tools)} tools from McpConfigToolkit ({server_name})")
344
+ except Exception as e:
345
+ logger.error(f"❌ Failed to initialize McpConfigToolkit: {e}")
346
+ if not debug_mode:
347
+ raise
348
+ except McpAuthorizationRequired:
349
+ # Re-raise auth required exceptions directly
350
+ raise
351
+ except Exception as e:
352
+ logger.error(f"Error initializing toolkit for tool '{tool.get('name', 'unknown')}': {e}", exc_info=True)
353
+ if debug_mode:
354
+ logger.info("Skipping tool initialization error due to debug mode.")
355
+ continue
356
+ else:
357
+ raise ToolException(f"Error initializing toolkit for tool '{tool.get('name', 'unknown')}': {e}")
358
+
359
+ # Track unhandled tools (make a copy to avoid reference issues)
360
+ if not tool_handled:
361
+ # Ensure we only add valid tool configurations to unhandled_tools
362
+ if isinstance(tool, dict) and 'type' in tool and isinstance(tool['type'], str):
363
+ unhandled_tools.append(dict(tool))
364
+
95
365
  if len(prompts) > 0:
96
366
  tools += PromptToolkit.get_toolkit(alita_client, prompts).get_tools()
97
-
98
- # Add community tools
99
- tools += community_tools(tools_list, alita_client, llm)
100
- # Add alita tools
101
- tools += alita_tools(tools_list, alita_client, llm, memory_store)
102
- # Add MCP tools
103
- tools += _mcp_tools(tools_list, alita_client)
367
+
368
+ # Add community tools (only for unhandled tools)
369
+ tools += community_tools(unhandled_tools, alita_client, llm)
370
+ # Add alita tools (only for unhandled tools)
371
+ tools += alita_tools(unhandled_tools, alita_client, llm, memory_store)
372
+ # Add MCP tools registered via alita-mcp CLI (static registry)
373
+ # Note: Tools with type='mcp' are already handled in main loop above
374
+ tools += _mcp_tools(unhandled_tools, alita_client)
104
375
 
105
376
  # Sanitize tool names to meet OpenAI's function naming requirements
106
377
  # tools = _sanitize_tool_names(tools)
@@ -154,6 +425,10 @@ def _sanitize_tool_names(tools: list) -> list:
154
425
 
155
426
 
156
427
  def _mcp_tools(tools_list, alita):
428
+ """
429
+ Handle MCP tools registered via alita-mcp CLI (static registry).
430
+ Skips tools with type='mcp' as those are handled by dynamic discovery.
431
+ """
157
432
  try:
158
433
  all_available_toolkits = alita.get_mcp_toolkits()
159
434
  toolkit_lookup = {tk["name"]: tk for tk in all_available_toolkits}
@@ -161,6 +436,11 @@ def _mcp_tools(tools_list, alita):
161
436
  #
162
437
  for selected_toolkit in tools_list:
163
438
  server_toolkit_name = selected_toolkit['type']
439
+
440
+ # Skip tools with type='mcp' - they're handled by dynamic discovery
441
+ if server_toolkit_name == 'mcp':
442
+ continue
443
+
164
444
  toolkit_conf = toolkit_lookup.get(server_toolkit_name)
165
445
  #
166
446
  if not toolkit_conf:
@@ -186,11 +466,18 @@ def _mcp_tools(tools_list, alita):
186
466
 
187
467
  def _init_single_mcp_tool(server_toolkit_name, toolkit_name, available_tool, alita, toolkit_settings):
188
468
  try:
189
-
190
- tool_name = f'{toolkit_name}{TOOLKIT_SPLITTER}{available_tool["name"]}'
469
+ # Use clean tool name without prefix
470
+ tool_name = available_tool["name"]
471
+ # Add toolkit context to description (max 1000 chars)
472
+ toolkit_context = f" [Toolkit: {clean_string(toolkit_name)}]" if toolkit_name else ''
473
+ base_description = f"MCP for a tool '{tool_name}': {available_tool.get('description', '')}"
474
+ description = base_description
475
+ if toolkit_context and len(base_description + toolkit_context) <= 1000:
476
+ description = base_description + toolkit_context
477
+
191
478
  return McpServerTool(
192
479
  name=tool_name,
193
- description=f"MCP for a tool '{tool_name}': {available_tool.get("description", "")}",
480
+ description=description,
194
481
  args_schema=McpServerTool.create_pydantic_model_from_schema(
195
482
  available_tool.get("inputSchema", {})
196
483
  ),
@@ -1,7 +1,7 @@
1
1
  from logging import getLogger
2
2
  from typing import Any, List, Literal, Optional
3
3
 
4
- from alita_sdk.tools.utils import clean_string, TOOLKIT_SPLITTER
4
+ from alita_sdk.tools.utils import clean_string
5
5
  from pydantic import BaseModel, create_model, Field, ConfigDict
6
6
  from langchain_core.tools import BaseToolkit, BaseTool
7
7
  from alita_sdk.tools.base.tool import BaseAction
@@ -31,7 +31,8 @@ class VectorStoreToolkit(BaseToolkit):
31
31
  toolkit_name: Optional[str] = None,
32
32
  selected_tools: list[str] = []):
33
33
  logger.info("Selected tools: %s", selected_tools)
34
- prefix = clean_string(toolkit_name) + TOOLKIT_SPLITTER if toolkit_name else ''
34
+ # Use clean toolkit name for context (max 1000 chars in description)
35
+ toolkit_context = f" [Toolkit: {clean_string(toolkit_name)}]" if toolkit_name else ''
35
36
  if selected_tools is None:
36
37
  selected_tools = []
37
38
  tools = []
@@ -46,11 +47,16 @@ class VectorStoreToolkit(BaseToolkit):
46
47
  # if selected_tools:
47
48
  # if tool["name"] not in selected_tools:
48
49
  # continue
50
+ # Add toolkit context to description with character limit
51
+ description = tool["description"]
52
+ if toolkit_context and len(description + toolkit_context) <= 1000:
53
+ description = description + toolkit_context
49
54
  tools.append(BaseAction(
50
55
  api_wrapper=vectorstore_wrapper,
51
- name=f'{prefix}{tool["name"]}',
52
- description=tool["description"],
53
- args_schema=tool["args_schema"]
56
+ name=tool["name"],
57
+ description=description,
58
+ args_schema=tool["args_schema"],
59
+ metadata={"toolkit_name": toolkit_name, "toolkit_type": "vectorstore"} if toolkit_name else {}
54
60
  ))
55
61
  return cls(tools=tools)
56
62
 
@@ -5,7 +5,12 @@ This module provides various tools that can be used within LangGraph agents.
5
5
 
6
6
  from .sandbox import PyodideSandboxTool, StatefulPyodideSandboxTool, create_sandbox_tool
7
7
  from .echo import EchoTool
8
- from .image_generation import ImageGenerationTool, create_image_generation_tool
8
+ from .image_generation import (
9
+ ImageGenerationTool,
10
+ create_image_generation_tool,
11
+ ImageGenerationToolkit
12
+ )
13
+ from .skill_router import SkillRouterWrapper
9
14
 
10
15
  __all__ = [
11
16
  "PyodideSandboxTool",
@@ -13,5 +18,7 @@ __all__ = [
13
18
  "create_sandbox_tool",
14
19
  "EchoTool",
15
20
  "ImageGenerationTool",
16
- "create_image_generation_tool"
17
- ]
21
+ "ImageGenerationToolkit",
22
+ "create_image_generation_tool",
23
+ "SkillRouterWrapper"
24
+ ]
@@ -4,7 +4,7 @@ from ..utils.utils import clean_string
4
4
  from langchain_core.tools import BaseTool, ToolException
5
5
  from langchain_core.messages import BaseMessage, AIMessage, HumanMessage
6
6
  from typing import Any, Type, Optional
7
- from pydantic import create_model, field_validator, BaseModel
7
+ from pydantic import create_model, model_validator, BaseModel
8
8
  from pydantic.fields import FieldInfo
9
9
  from ..langchain.mixedAgentRenderes import convert_message_to_json
10
10
  from logging import getLogger
@@ -41,8 +41,7 @@ def formulate_query(kwargs):
41
41
  if key not in ("task", "chat_history"):
42
42
  result[key] = value
43
43
  return result
44
-
45
-
44
+
46
45
 
47
46
  class Application(BaseTool):
48
47
  name: str
@@ -50,11 +49,26 @@ class Application(BaseTool):
50
49
  application: Any
51
50
  args_schema: Type[BaseModel] = applicationToolSchema
52
51
  return_type: str = "str"
52
+ client: Any
53
+ args_runnable: dict = {}
54
+ metadata: dict = {}
55
+ is_subgraph: Optional[bool] = False
53
56
 
54
- @field_validator('name', mode='before')
57
+ @model_validator(mode='before')
55
58
  @classmethod
56
- def remove_spaces(cls, v):
57
- return clean_string(v)
59
+ def preserve_original_name(cls, data: Any) -> Any:
60
+ """Preserve the original name in metadata before cleaning."""
61
+ if isinstance(data, dict):
62
+ original_name = data.get('name')
63
+ if original_name:
64
+ # Initialize metadata if not present
65
+ if data.get('metadata') is None:
66
+ data['metadata'] = {}
67
+ # Store original name before cleaning
68
+ data['metadata']['original_name'] = original_name
69
+ # Clean the name
70
+ data['name'] = clean_string(original_name)
71
+ return data
58
72
 
59
73
  def invoke(self, input: Any, config: Optional[dict] = None, **kwargs: Any) -> Any:
60
74
  """Override default invoke to preserve all fields, not just args_schema"""
@@ -66,7 +80,14 @@ class Application(BaseTool):
66
80
  return self._run(*config, **all_kwargs)
67
81
 
68
82
  def _run(self, *args, **kwargs):
83
+ if self.client and self.args_runnable:
84
+ # Recreate new LanggraphAgentRunnable in order to reflect the current input_mapping (it can be dynamic for pipelines).
85
+ # Actually, for pipelines agent toolkits LanggraphAgentRunnable is created (for LLMNode) before pipeline's schema parsing.
86
+ application_variables = {k: {"name": k, "value": v} for k, v in kwargs.items()}
87
+ self.application = self.client.application(**self.args_runnable, application_variables=application_variables)
69
88
  response = self.application.invoke(formulate_query(kwargs))
89
+ if self.is_subgraph:
90
+ return response
70
91
  if self.return_type == "str":
71
92
  return response["output"]
72
93
  else: