vellum-ai 1.11.2__py3-none-any.whl → 1.13.5__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 vellum-ai might be problematic. Click here for more details.

Files changed (275) hide show
  1. vellum/__init__.py +18 -0
  2. vellum/client/README.md +1 -1
  3. vellum/client/core/client_wrapper.py +2 -2
  4. vellum/client/core/force_multipart.py +4 -2
  5. vellum/client/core/http_response.py +1 -1
  6. vellum/client/core/pydantic_utilities.py +7 -4
  7. vellum/client/errors/too_many_requests_error.py +1 -2
  8. vellum/client/reference.md +677 -76
  9. vellum/client/resources/container_images/client.py +299 -0
  10. vellum/client/resources/container_images/raw_client.py +286 -0
  11. vellum/client/resources/documents/client.py +20 -10
  12. vellum/client/resources/documents/raw_client.py +20 -10
  13. vellum/client/resources/events/raw_client.py +4 -4
  14. vellum/client/resources/integration_auth_configs/client.py +2 -0
  15. vellum/client/resources/integration_auth_configs/raw_client.py +2 -0
  16. vellum/client/resources/integration_providers/client.py +28 -2
  17. vellum/client/resources/integration_providers/raw_client.py +24 -0
  18. vellum/client/resources/integrations/client.py +52 -4
  19. vellum/client/resources/integrations/raw_client.py +61 -0
  20. vellum/client/resources/workflow_deployments/client.py +156 -0
  21. vellum/client/resources/workflow_deployments/raw_client.py +334 -0
  22. vellum/client/resources/workflows/client.py +212 -8
  23. vellum/client/resources/workflows/raw_client.py +343 -6
  24. vellum/client/types/__init__.py +18 -0
  25. vellum/client/types/api_actor_type_enum.py +1 -1
  26. vellum/client/types/check_workflow_execution_status_error.py +21 -0
  27. vellum/client/types/check_workflow_execution_status_response.py +29 -0
  28. vellum/client/types/code_execution_package_request.py +21 -0
  29. vellum/client/types/composio_execute_tool_request.py +5 -0
  30. vellum/client/types/composio_tool_definition.py +1 -0
  31. vellum/client/types/container_image_build_config.py +1 -0
  32. vellum/client/types/container_image_container_image_tag.py +1 -0
  33. vellum/client/types/dataset_row_push_request.py +3 -0
  34. vellum/client/types/document_document_to_document_index.py +1 -0
  35. vellum/client/types/integration_name.py +24 -0
  36. vellum/client/types/node_execution_fulfilled_body.py +1 -0
  37. vellum/client/types/node_execution_log_body.py +24 -0
  38. vellum/client/types/node_execution_log_event.py +47 -0
  39. vellum/client/types/prompt_deployment_release_prompt_deployment.py +1 -0
  40. vellum/client/types/runner_config_request.py +24 -0
  41. vellum/client/types/severity_enum.py +5 -0
  42. vellum/client/types/slim_composio_tool_definition.py +1 -0
  43. vellum/client/types/slim_document_document_to_document_index.py +2 -0
  44. vellum/client/types/type_checker_enum.py +5 -0
  45. vellum/client/types/vellum_audio.py +5 -1
  46. vellum/client/types/vellum_audio_request.py +5 -1
  47. vellum/client/types/vellum_document.py +5 -1
  48. vellum/client/types/vellum_document_request.py +5 -1
  49. vellum/client/types/vellum_image.py +5 -1
  50. vellum/client/types/vellum_image_request.py +5 -1
  51. vellum/client/types/vellum_node_execution_event.py +2 -0
  52. vellum/client/types/vellum_variable.py +5 -0
  53. vellum/client/types/vellum_variable_extensions.py +1 -0
  54. vellum/client/types/vellum_variable_type.py +1 -0
  55. vellum/client/types/vellum_video.py +5 -1
  56. vellum/client/types/vellum_video_request.py +5 -1
  57. vellum/client/types/workflow_deployment_release_workflow_deployment.py +1 -0
  58. vellum/client/types/workflow_event.py +2 -0
  59. vellum/client/types/workflow_execution_fulfilled_body.py +1 -0
  60. vellum/client/types/workflow_result_event_output_data_array.py +1 -1
  61. vellum/client/types/workflow_result_event_output_data_chat_history.py +1 -1
  62. vellum/client/types/workflow_result_event_output_data_error.py +1 -1
  63. vellum/client/types/workflow_result_event_output_data_function_call.py +1 -1
  64. vellum/client/types/workflow_result_event_output_data_json.py +1 -1
  65. vellum/client/types/workflow_result_event_output_data_number.py +1 -1
  66. vellum/client/types/workflow_result_event_output_data_search_results.py +1 -1
  67. vellum/client/types/workflow_result_event_output_data_string.py +1 -1
  68. vellum/client/types/workflow_sandbox_execute_node_response.py +8 -0
  69. vellum/plugins/vellum_mypy.py +37 -2
  70. vellum/types/check_workflow_execution_status_error.py +3 -0
  71. vellum/types/check_workflow_execution_status_response.py +3 -0
  72. vellum/types/code_execution_package_request.py +3 -0
  73. vellum/types/node_execution_log_body.py +3 -0
  74. vellum/types/node_execution_log_event.py +3 -0
  75. vellum/types/runner_config_request.py +3 -0
  76. vellum/types/severity_enum.py +3 -0
  77. vellum/types/type_checker_enum.py +3 -0
  78. vellum/types/workflow_sandbox_execute_node_response.py +3 -0
  79. vellum/utils/files/mixin.py +26 -0
  80. vellum/utils/files/tests/test_mixin.py +62 -0
  81. vellum/utils/tests/test_vellum_client.py +95 -0
  82. vellum/utils/uuid.py +19 -2
  83. vellum/utils/vellum_client.py +10 -3
  84. vellum/workflows/__init__.py +7 -1
  85. vellum/workflows/descriptors/base.py +86 -0
  86. vellum/workflows/descriptors/tests/test_utils.py +9 -0
  87. vellum/workflows/errors/tests/__init__.py +0 -0
  88. vellum/workflows/errors/tests/test_types.py +52 -0
  89. vellum/workflows/errors/types.py +1 -0
  90. vellum/workflows/events/node.py +24 -0
  91. vellum/workflows/events/tests/test_event.py +123 -0
  92. vellum/workflows/events/types.py +2 -1
  93. vellum/workflows/events/workflow.py +28 -2
  94. vellum/workflows/expressions/add.py +3 -0
  95. vellum/workflows/expressions/tests/test_add.py +24 -0
  96. vellum/workflows/graph/graph.py +26 -5
  97. vellum/workflows/graph/tests/test_graph.py +228 -1
  98. vellum/workflows/inputs/base.py +22 -6
  99. vellum/workflows/inputs/dataset_row.py +121 -16
  100. vellum/workflows/inputs/tests/test_inputs.py +3 -3
  101. vellum/workflows/integrations/tests/test_vellum_integration_service.py +84 -0
  102. vellum/workflows/integrations/vellum_integration_service.py +12 -1
  103. vellum/workflows/loaders/base.py +2 -0
  104. vellum/workflows/nodes/bases/base.py +37 -16
  105. vellum/workflows/nodes/bases/tests/test_base_node.py +104 -1
  106. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
  107. vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +1 -1
  108. vellum/workflows/nodes/core/map_node/node.py +7 -5
  109. vellum/workflows/nodes/core/map_node/tests/test_node.py +33 -0
  110. vellum/workflows/nodes/core/retry_node/node.py +1 -0
  111. vellum/workflows/nodes/core/try_node/node.py +1 -0
  112. vellum/workflows/nodes/displayable/api_node/node.py +3 -2
  113. vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +38 -0
  114. vellum/workflows/nodes/displayable/bases/api_node/node.py +1 -1
  115. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +18 -1
  116. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +109 -2
  117. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +13 -2
  118. vellum/workflows/nodes/displayable/code_execution_node/node.py +9 -15
  119. vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +65 -24
  120. vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -0
  121. vellum/workflows/nodes/displayable/final_output_node/node.py +24 -69
  122. vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py +53 -3
  123. vellum/workflows/nodes/displayable/note_node/node.py +4 -1
  124. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +16 -5
  125. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +47 -0
  126. vellum/workflows/nodes/displayable/tool_calling_node/node.py +74 -34
  127. vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +204 -8
  128. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +92 -71
  129. vellum/workflows/nodes/mocks.py +47 -213
  130. vellum/workflows/nodes/tests/test_mocks.py +0 -177
  131. vellum/workflows/nodes/utils.py +23 -8
  132. vellum/workflows/outputs/base.py +36 -3
  133. vellum/workflows/references/environment_variable.py +1 -11
  134. vellum/workflows/references/lazy.py +8 -0
  135. vellum/workflows/references/state_value.py +24 -1
  136. vellum/workflows/references/tests/test_lazy.py +58 -0
  137. vellum/workflows/references/trigger.py +8 -3
  138. vellum/workflows/references/workflow_input.py +8 -0
  139. vellum/workflows/resolvers/resolver.py +13 -3
  140. vellum/workflows/resolvers/tests/test_resolver.py +31 -0
  141. vellum/workflows/runner/runner.py +159 -14
  142. vellum/workflows/runner/tests/__init__.py +0 -0
  143. vellum/workflows/runner/tests/test_runner.py +170 -0
  144. vellum/workflows/sandbox.py +7 -8
  145. vellum/workflows/state/base.py +89 -30
  146. vellum/workflows/state/context.py +74 -3
  147. vellum/workflows/state/tests/test_state.py +269 -1
  148. vellum/workflows/tests/test_dataset_row.py +8 -7
  149. vellum/workflows/tests/test_sandbox.py +97 -8
  150. vellum/workflows/triggers/__init__.py +2 -1
  151. vellum/workflows/triggers/base.py +160 -28
  152. vellum/workflows/triggers/chat_message.py +141 -0
  153. vellum/workflows/triggers/integration.py +12 -0
  154. vellum/workflows/triggers/manual.py +3 -1
  155. vellum/workflows/triggers/schedule.py +3 -1
  156. vellum/workflows/triggers/tests/test_chat_message.py +257 -0
  157. vellum/workflows/types/core.py +18 -0
  158. vellum/workflows/types/definition.py +6 -13
  159. vellum/workflows/types/generics.py +12 -0
  160. vellum/workflows/types/tests/test_utils.py +12 -0
  161. vellum/workflows/types/utils.py +32 -2
  162. vellum/workflows/types/workflow_metadata.py +124 -0
  163. vellum/workflows/utils/functions.py +152 -16
  164. vellum/workflows/utils/pydantic_schema.py +19 -1
  165. vellum/workflows/utils/tests/test_functions.py +123 -8
  166. vellum/workflows/utils/tests/test_validate.py +79 -0
  167. vellum/workflows/utils/tests/test_vellum_variables.py +62 -2
  168. vellum/workflows/utils/uuids.py +90 -0
  169. vellum/workflows/utils/validate.py +108 -0
  170. vellum/workflows/utils/vellum_variables.py +96 -16
  171. vellum/workflows/workflows/base.py +177 -35
  172. vellum/workflows/workflows/tests/test_base_workflow.py +51 -0
  173. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/METADATA +6 -1
  174. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/RECORD +274 -227
  175. vellum_cli/__init__.py +21 -0
  176. vellum_cli/config.py +16 -2
  177. vellum_cli/pull.py +2 -0
  178. vellum_cli/push.py +23 -10
  179. vellum_cli/tests/conftest.py +8 -13
  180. vellum_cli/tests/test_image_push.py +4 -11
  181. vellum_cli/tests/test_pull.py +83 -68
  182. vellum_cli/tests/test_push.py +251 -2
  183. vellum_ee/assets/node-definitions.json +225 -12
  184. vellum_ee/scripts/generate_node_definitions.py +15 -3
  185. vellum_ee/workflows/display/base.py +4 -3
  186. vellum_ee/workflows/display/nodes/base_node_display.py +44 -11
  187. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +93 -0
  188. vellum_ee/workflows/display/nodes/types.py +1 -0
  189. vellum_ee/workflows/display/nodes/vellum/__init__.py +0 -2
  190. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +5 -2
  191. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
  192. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +10 -2
  193. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +17 -14
  194. vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -0
  195. vellum_ee/workflows/display/nodes/vellum/note_node.py +18 -3
  196. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +37 -14
  197. vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +62 -2
  198. vellum_ee/workflows/display/nodes/vellum/tests/test_final_output_node.py +136 -0
  199. vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +44 -7
  200. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +5 -13
  201. vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +27 -17
  202. vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +145 -22
  203. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +107 -2
  204. vellum_ee/workflows/display/nodes/vellum/utils.py +54 -12
  205. vellum_ee/workflows/display/tests/test_base_workflow_display.py +13 -16
  206. vellum_ee/workflows/display/tests/test_json_schema_validation.py +190 -0
  207. vellum_ee/workflows/display/tests/test_mocks.py +912 -0
  208. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +14 -2
  209. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +109 -0
  210. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +3 -0
  211. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +187 -1
  212. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +34 -325
  213. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +42 -393
  214. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +13 -315
  215. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +2 -122
  216. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +24 -115
  217. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -93
  218. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -80
  219. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +9 -101
  220. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +77 -308
  221. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +62 -324
  222. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -82
  223. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +4 -142
  224. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +1 -61
  225. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_set_state_node_serialization.py +4 -4
  226. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +205 -134
  227. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +34 -146
  228. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +2 -0
  229. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py +8 -6
  230. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +137 -266
  231. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_tool_wrapper_serialization.py +84 -0
  232. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_mcp_serialization.py +55 -16
  233. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +15 -1
  234. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_tool_wrapper_serialization.py +71 -0
  235. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_vellum_integration_serialization.py +119 -0
  236. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py +1 -1
  237. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -2
  238. vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_dict_reference_serialization.py +22 -1
  239. vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_trigger_serialization.py +412 -0
  240. vellum_ee/workflows/display/tests/workflow_serialization/test_code_tool_node_reference_error.py +106 -0
  241. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -41
  242. vellum_ee/workflows/display/tests/workflow_serialization/test_duplicate_trigger_name_validation.py +208 -0
  243. vellum_ee/workflows/display/tests/workflow_serialization/test_final_output_node_not_referenced_by_workflow_outputs.py +45 -0
  244. vellum_ee/workflows/display/tests/workflow_serialization/test_infinite_loop_validation.py +66 -0
  245. vellum_ee/workflows/display/tests/workflow_serialization/test_int_input_serialization.py +40 -0
  246. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_serialization.py +8 -14
  247. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_validation.py +173 -0
  248. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_with_entrypoint_node_id.py +16 -13
  249. vellum_ee/workflows/display/tests/workflow_serialization/test_list_vellum_document_serialization.py +5 -1
  250. vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +12 -2
  251. vellum_ee/workflows/display/tests/workflow_serialization/test_multi_trigger_same_node_serialization.py +111 -0
  252. vellum_ee/workflows/display/tests/workflow_serialization/test_no_triggers_no_entrypoint_validation.py +64 -0
  253. vellum_ee/workflows/display/tests/workflow_serialization/test_partial_workflow_meta_display_override.py +55 -0
  254. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_dataset_mocks_serialization.py +268 -0
  255. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_invalid_pdf_data_url.py +49 -0
  256. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_validation_errors.py +112 -0
  257. vellum_ee/workflows/display/tests/workflow_serialization/test_scheduled_trigger_serialization.py +25 -16
  258. vellum_ee/workflows/display/tests/workflow_serialization/test_terminal_node_in_unused_graphs_serialization.py +53 -0
  259. vellum_ee/workflows/display/utils/exceptions.py +34 -0
  260. vellum_ee/workflows/display/utils/expressions.py +463 -52
  261. vellum_ee/workflows/display/utils/metadata.py +98 -33
  262. vellum_ee/workflows/display/utils/tests/test_metadata.py +31 -0
  263. vellum_ee/workflows/display/utils/triggers.py +153 -0
  264. vellum_ee/workflows/display/utils/vellum.py +59 -5
  265. vellum_ee/workflows/display/workflows/base_workflow_display.py +656 -254
  266. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +26 -0
  267. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +77 -29
  268. vellum_ee/workflows/server/namespaces.py +18 -0
  269. vellum_ee/workflows/tests/test_display_meta.py +2 -0
  270. vellum_ee/workflows/tests/test_serialize_module.py +174 -7
  271. vellum_ee/workflows/tests/test_server.py +0 -3
  272. vellum_ee/workflows/display/nodes/vellum/function_node.py +0 -14
  273. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/LICENSE +0 -0
  274. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/WHEEL +0 -0
  275. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/entry_points.txt +0 -0
@@ -3,7 +3,19 @@ from uuid import uuid4
3
3
 
4
4
  from deepdiff import DeepDiff
5
5
 
6
- from vellum import WorkflowDeploymentRead
6
+ from vellum import (
7
+ ReleaseEnvironment,
8
+ VellumVariable,
9
+ WorkflowDeploymentRelease,
10
+ WorkflowDeploymentReleaseWorkflowDeployment,
11
+ WorkflowDeploymentReleaseWorkflowVersion,
12
+ )
13
+ from vellum.workflows import BaseWorkflow
14
+ from vellum.workflows.inputs import BaseInputs
15
+ from vellum.workflows.nodes import SubworkflowDeploymentNode, TemplatingNode
16
+ from vellum.workflows.nodes.core.try_node.node import TryNode
17
+ from vellum.workflows.outputs import BaseOutputs
18
+ from vellum.workflows.state import BaseState
7
19
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
8
20
 
9
21
  from tests.workflows.basic_subworkflow_deployment.workflow import BasicSubworkflowDeploymentWorkflow
@@ -11,17 +23,24 @@ from tests.workflows.basic_subworkflow_deployment.workflow import BasicSubworkfl
11
23
 
12
24
  def test_serialize_workflow(vellum_client):
13
25
  # GIVEN a Workflow with stubbed out API calls
14
- deployment = WorkflowDeploymentRead(
26
+ deployment_id = str(uuid4())
27
+ deployment_release = WorkflowDeploymentRelease(
15
28
  id=str(uuid4()),
16
29
  created=datetime.now(),
17
- label="Example Subworkflow Deployment",
18
- name="example_subworkflow_deployment",
19
- input_variables=[],
20
- output_variables=[],
21
- last_deployed_on=datetime.now(),
22
- last_deployed_history_item_id=str(uuid4()),
30
+ environment=ReleaseEnvironment(id=str(uuid4()), name="DEVELOPMENT", label="Development"),
31
+ workflow_version=WorkflowDeploymentReleaseWorkflowVersion(
32
+ id=str(uuid4()),
33
+ input_variables=[],
34
+ output_variables=[],
35
+ ),
36
+ deployment=WorkflowDeploymentReleaseWorkflowDeployment(
37
+ id=deployment_id,
38
+ name="example_subworkflow_deployment",
39
+ ),
40
+ release_tags=[],
41
+ reviews=[],
23
42
  )
24
- vellum_client.workflow_deployments.retrieve.return_value = deployment
43
+ vellum_client.workflow_deployments.retrieve_workflow_deployment_release.return_value = deployment_release
25
44
 
26
45
  # WHEN we serialize it
27
46
  workflow_display = get_workflow_display(workflow_class=BasicSubworkflowDeploymentWorkflow)
@@ -47,6 +66,7 @@ def test_serialize_workflow(vellum_client):
47
66
  "required": True,
48
67
  "default": None,
49
68
  "extensions": {"color": None},
69
+ "schema": {"type": "string"},
50
70
  },
51
71
  {
52
72
  "id": "19a78824-9a98-4ae8-a1fc-61f81a422a17",
@@ -55,6 +75,7 @@ def test_serialize_workflow(vellum_client):
55
75
  "required": True,
56
76
  "default": None,
57
77
  "extensions": {"color": None},
78
+ "schema": {"type": "string"},
58
79
  },
59
80
  ],
60
81
  input_variables,
@@ -83,8 +104,6 @@ def test_serialize_workflow(vellum_client):
83
104
 
84
105
  # AND its raw data should be what we expect
85
106
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
86
- assert len(workflow_raw_data["edges"]) == 3
87
- assert len(workflow_raw_data["nodes"]) == 4
88
107
 
89
108
  # AND each node should be serialized correctly
90
109
  entrypoint_node = workflow_raw_data["nodes"][0]
@@ -141,7 +160,7 @@ def test_serialize_workflow(vellum_client):
141
160
  "source_handle_id": "ff99bf0c-c239-4b8b-8ac1-483b134f94f4",
142
161
  "target_handle_id": "d6194ccf-d31b-4846-8e24-3e189d84351a",
143
162
  "variant": "DEPLOYMENT",
144
- "workflow_deployment_id": deployment.id,
163
+ "workflow_deployment_id": deployment_id,
145
164
  "release_tag": "LATEST",
146
165
  },
147
166
  "display_data": {"position": {"x": 200.0, "y": -50.0}},
@@ -158,133 +177,23 @@ def test_serialize_workflow(vellum_client):
158
177
  "merge_behavior": "AWAIT_ANY",
159
178
  },
160
179
  "ports": [{"id": "ff99bf0c-c239-4b8b-8ac1-483b134f94f4", "name": "default", "type": "DEFAULT"}],
161
- }
162
-
163
- assert not DeepDiff(
164
- [
165
- {
166
- "id": "18170041-1a70-4836-9fa0-adceba2a1f4f",
167
- "type": "TERMINAL",
168
- "base": {
169
- "module": [
170
- "vellum",
171
- "workflows",
172
- "nodes",
173
- "displayable",
174
- "final_output_node",
175
- "node",
176
- ],
177
- "name": "FinalOutputNode",
178
- },
179
- "definition": None,
180
- "data": {
181
- "label": "Final Output",
182
- "name": "temperature",
183
- "target_handle_id": "23117248-df28-4519-bebc-abcb24f966b3",
184
- "output_id": "3f487916-126f-4d6c-95b4-fa72d875b793",
185
- "output_type": "NUMBER",
186
- "node_input_id": "6f4955d8-8a3f-4db7-8293-7affc5877dcd",
187
- },
188
- "inputs": [
189
- {
190
- "id": "6f4955d8-8a3f-4db7-8293-7affc5877dcd",
191
- "key": "node_input",
192
- "value": {
193
- "rules": [
194
- {
195
- "type": "NODE_OUTPUT",
196
- "data": {
197
- "node_id": "bb98a2c4-c9a7-4c39-8f31-dc7961dc9996",
198
- "output_id": "d901cbed-9905-488c-be62-e2668f85438f",
199
- },
200
- }
201
- ],
202
- "combinator": "OR",
203
- },
204
- }
205
- ],
206
- "display_data": {"position": {"x": 400.0, "y": -175.0}},
207
- },
208
- {
209
- "id": "94afd0ac-1ec4-486b-a6fb-fa1ec7029d19",
210
- "type": "TERMINAL",
211
- "base": {
212
- "module": [
213
- "vellum",
214
- "workflows",
215
- "nodes",
216
- "displayable",
217
- "final_output_node",
218
- "node",
219
- ],
220
- "name": "FinalOutputNode",
221
- },
222
- "definition": None,
223
- "data": {
224
- "label": "Final Output",
225
- "name": "reasoning",
226
- "target_handle_id": "c3aeba92-4faf-4814-9842-eec7436ee555",
227
- "output_id": "45d53a1e-26e8-4c43-a010-80d141acc249",
228
- "output_type": "STRING",
229
- "node_input_id": "74337307-3fcb-42c5-9aed-98bd4a79caef",
230
- },
231
- "inputs": [
232
- {
233
- "id": "74337307-3fcb-42c5-9aed-98bd4a79caef",
234
- "key": "node_input",
235
- "value": {
236
- "rules": [
237
- {
238
- "type": "NODE_OUTPUT",
239
- "data": {
240
- "node_id": "bb98a2c4-c9a7-4c39-8f31-dc7961dc9996",
241
- "output_id": "68de689c-fe8a-4189-b7d0-82c620ac30f9",
242
- },
243
- }
244
- ],
245
- "combinator": "OR",
246
- },
247
- }
248
- ],
249
- "display_data": {"position": {"x": 400.0, "y": 75.0}},
250
- },
251
- ],
252
- workflow_raw_data["nodes"][2:],
253
- ignore_order=True,
254
- )
255
-
256
- # AND each edge should be serialized correctly
257
- serialized_edges = workflow_raw_data["edges"]
258
- assert not DeepDiff(
259
- [
260
- {
261
- "id": "4a08ef93-c0f4-4a3a-9a24-5d79ee4d85fc",
262
- "source_handle_id": "13d9eb34-aecb-496d-9e57-d5e786b0bc7c",
263
- "source_node_id": "f0eea82b-39cc-44e3-9c0d-12205ed5652c",
264
- "target_handle_id": "d6194ccf-d31b-4846-8e24-3e189d84351a",
265
- "target_node_id": "bb98a2c4-c9a7-4c39-8f31-dc7961dc9996",
266
- "type": "DEFAULT",
267
- },
180
+ "outputs": [
268
181
  {
269
- "id": "69933897-e91e-4c6c-9ba3-ed3e3c265c73",
270
- "source_handle_id": "ff99bf0c-c239-4b8b-8ac1-483b134f94f4",
271
- "source_node_id": "bb98a2c4-c9a7-4c39-8f31-dc7961dc9996",
272
- "target_handle_id": "c3aeba92-4faf-4814-9842-eec7436ee555",
273
- "target_node_id": "94afd0ac-1ec4-486b-a6fb-fa1ec7029d19",
274
- "type": "DEFAULT",
182
+ "id": "d901cbed-9905-488c-be62-e2668f85438f",
183
+ "name": "temperature",
184
+ "schema": {"type": "number"},
185
+ "type": "NUMBER",
186
+ "value": None,
275
187
  },
276
188
  {
277
- "id": "86a9af31-f78e-45ac-b170-f66bbba98f9d",
278
- "source_handle_id": "ff99bf0c-c239-4b8b-8ac1-483b134f94f4",
279
- "source_node_id": "bb98a2c4-c9a7-4c39-8f31-dc7961dc9996",
280
- "target_handle_id": "23117248-df28-4519-bebc-abcb24f966b3",
281
- "target_node_id": "18170041-1a70-4836-9fa0-adceba2a1f4f",
282
- "type": "DEFAULT",
189
+ "id": "68de689c-fe8a-4189-b7d0-82c620ac30f9",
190
+ "name": "reasoning",
191
+ "schema": {"type": "string"},
192
+ "type": "STRING",
193
+ "value": None,
283
194
  },
284
195
  ],
285
- serialized_edges,
286
- ignore_order=True,
287
- )
196
+ }
288
197
 
289
198
  # AND the display data should be what we expect
290
199
  display_data = workflow_raw_data["display_data"]
@@ -307,3 +216,165 @@ def test_serialize_workflow(vellum_client):
307
216
  "workflow",
308
217
  ],
309
218
  }
219
+
220
+
221
+ def test_serialize_workflow__subworkflow_deployment_node_outputs_from_release(vellum_client):
222
+ """
223
+ Tests that subworkflow deployment node outputs are populated from the deployment's output variables,
224
+ and that downstream nodes referencing those outputs correctly reference the subworkflow node.
225
+ """
226
+
227
+ # GIVEN a subworkflow deployment node with foo and bar outputs
228
+ class SubworkflowDeploymentNodeWithOutputs(SubworkflowDeploymentNode):
229
+ deployment = "test_subworkflow_deployment"
230
+
231
+ class Outputs(BaseOutputs):
232
+ foo: str
233
+ bar: int
234
+
235
+ # AND a templating node that references both outputs
236
+ class ConsumingNode(TemplatingNode):
237
+ template = "foo: {{ foo }}, bar: {{ bar }}"
238
+ inputs = {
239
+ "foo": SubworkflowDeploymentNodeWithOutputs.Outputs.foo,
240
+ "bar": SubworkflowDeploymentNodeWithOutputs.Outputs.bar,
241
+ }
242
+
243
+ class TestWorkflow(BaseWorkflow[BaseInputs, BaseState]):
244
+ graph = SubworkflowDeploymentNodeWithOutputs >> ConsumingNode
245
+
246
+ class Outputs(BaseOutputs):
247
+ result = ConsumingNode.Outputs.result
248
+
249
+ # AND a deployment release with output variables for foo and bar
250
+ foo_output_id = "11111111-1111-1111-1111-111111111111"
251
+ bar_output_id = "22222222-2222-2222-2222-222222222222"
252
+ deployment_release = WorkflowDeploymentRelease(
253
+ id=str(uuid4()),
254
+ created=datetime.now(),
255
+ environment=ReleaseEnvironment(id=str(uuid4()), name="DEVELOPMENT", label="Development"),
256
+ workflow_version=WorkflowDeploymentReleaseWorkflowVersion(
257
+ id=str(uuid4()),
258
+ input_variables=[],
259
+ output_variables=[
260
+ VellumVariable(id=foo_output_id, key="foo", type="STRING"),
261
+ VellumVariable(id=bar_output_id, key="bar", type="NUMBER"),
262
+ ],
263
+ ),
264
+ deployment=WorkflowDeploymentReleaseWorkflowDeployment(
265
+ id=str(uuid4()),
266
+ name="test_subworkflow_deployment",
267
+ ),
268
+ release_tags=[],
269
+ reviews=[],
270
+ )
271
+ vellum_client.workflow_deployments.retrieve_workflow_deployment_release.return_value = deployment_release
272
+
273
+ # WHEN we serialize the workflow
274
+ workflow_display = get_workflow_display(workflow_class=TestWorkflow)
275
+ serialized_workflow: dict = workflow_display.serialize()
276
+
277
+ # THEN the subworkflow deployment node should have outputs populated from the deployment's output variables
278
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
279
+ subworkflow_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "SUBWORKFLOW")
280
+
281
+ # AND the outputs should contain foo and bar with the correct IDs from the deployment
282
+ assert subworkflow_node.get("outputs") is not None, "outputs field should not be None"
283
+ outputs = subworkflow_node["outputs"]
284
+ assert len(outputs) == 2
285
+
286
+ foo_output = next((o for o in outputs if o["name"] == "foo"), None)
287
+ bar_output = next((o for o in outputs if o["name"] == "bar"), None)
288
+
289
+ assert foo_output is not None, "foo output should exist"
290
+ assert bar_output is not None, "bar output should exist"
291
+ assert foo_output["id"] == foo_output_id, "foo output ID should match deployment's output variable ID"
292
+ assert bar_output["id"] == bar_output_id, "bar output ID should match deployment's output variable ID"
293
+ assert foo_output["type"] == "STRING"
294
+ assert bar_output["type"] == "NUMBER"
295
+
296
+ # AND the consuming node should reference the subworkflow node's outputs
297
+ consuming_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "TEMPLATING")
298
+ consuming_node_inputs = consuming_node["inputs"]
299
+
300
+ foo_input = next((inp for inp in consuming_node_inputs if inp["key"] == "foo"), None)
301
+ bar_input = next((inp for inp in consuming_node_inputs if inp["key"] == "bar"), None)
302
+
303
+ assert foo_input is not None, "foo input should exist on consuming node"
304
+ assert bar_input is not None, "bar input should exist on consuming node"
305
+
306
+ # AND the foo input should reference the subworkflow node
307
+ foo_rule = foo_input["value"]["rules"][0]
308
+ assert foo_rule["type"] == "NODE_OUTPUT"
309
+ assert foo_rule["data"]["node_id"] == subworkflow_node["id"]
310
+ # The output_id should match the foo output from the subworkflow node's outputs list
311
+ assert foo_rule["data"]["output_id"] == foo_output["id"]
312
+
313
+ # AND the bar input should reference the subworkflow node
314
+ bar_rule = bar_input["value"]["rules"][0]
315
+ assert bar_rule["type"] == "NODE_OUTPUT"
316
+ assert bar_rule["data"]["node_id"] == subworkflow_node["id"]
317
+ # The output_id should match the bar output from the subworkflow node's outputs list
318
+ assert bar_rule["data"]["output_id"] == bar_output["id"]
319
+
320
+
321
+ def test_serialize_workflow__wrapped_subworkflow_deployment_node_calls_build_once(vellum_client):
322
+ """
323
+ Tests that a SubworkflowDeploymentNode wrapped in TryNode only calls the deployment
324
+ release API once during serialization, and that the serialized output contains the
325
+ correct deployment_id and release_tag.
326
+ """
327
+
328
+ # GIVEN a SubworkflowDeploymentNode wrapped in TryNode
329
+ @TryNode.wrap()
330
+ class WrappedSubworkflowDeploymentNode(SubworkflowDeploymentNode):
331
+ deployment = "test_wrapped_subworkflow_deployment"
332
+ release_tag = "LATEST"
333
+
334
+ class Outputs(BaseOutputs):
335
+ result: str
336
+
337
+ # AND a workflow that uses the wrapped node
338
+ class TestWorkflow(BaseWorkflow[BaseInputs, BaseState]):
339
+ graph = WrappedSubworkflowDeploymentNode
340
+
341
+ class Outputs(BaseOutputs):
342
+ final_result = WrappedSubworkflowDeploymentNode.Outputs.result
343
+
344
+ # AND a deployment release with specific deployment_id and release_tag
345
+ deployment_id = "test-deployment-id-12345"
346
+ result_output_id = "result-output-id-67890"
347
+ deployment_release = WorkflowDeploymentRelease(
348
+ id=str(uuid4()),
349
+ created=datetime.now(),
350
+ environment=ReleaseEnvironment(id=str(uuid4()), name="DEVELOPMENT", label="Development"),
351
+ workflow_version=WorkflowDeploymentReleaseWorkflowVersion(
352
+ id=str(uuid4()),
353
+ input_variables=[],
354
+ output_variables=[
355
+ VellumVariable(id=result_output_id, key="result", type="STRING"),
356
+ ],
357
+ ),
358
+ deployment=WorkflowDeploymentReleaseWorkflowDeployment(
359
+ id=deployment_id,
360
+ name="test_wrapped_subworkflow_deployment",
361
+ ),
362
+ release_tags=[],
363
+ reviews=[],
364
+ )
365
+ vellum_client.workflow_deployments.retrieve_workflow_deployment_release.return_value = deployment_release
366
+
367
+ # WHEN we serialize the workflow
368
+ workflow_display = get_workflow_display(workflow_class=TestWorkflow)
369
+ serialized_workflow: dict = workflow_display.serialize()
370
+
371
+ # THEN the deployment release API should only be called once
372
+ assert vellum_client.workflow_deployments.retrieve_workflow_deployment_release.call_count == 1
373
+
374
+ # AND the serialized subworkflow node should have the correct deployment_id
375
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
376
+ subworkflow_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "SUBWORKFLOW")
377
+ assert subworkflow_node["data"]["workflow_deployment_id"] == deployment_id
378
+
379
+ # AND the serialized subworkflow node should have the correct release_tag
380
+ assert subworkflow_node["data"]["release_tag"] == "LATEST"
@@ -32,6 +32,7 @@ def test_serialize_workflow():
32
32
  "default": None,
33
33
  "required": True,
34
34
  "extensions": {"color": None},
35
+ "schema": {},
35
36
  }
36
37
  ]
37
38
 
@@ -46,157 +47,44 @@ def test_serialize_workflow():
46
47
 
47
48
  # AND its raw data should be what we expect
48
49
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
49
- assert len(workflow_raw_data["edges"]) == 2
50
- assert len(workflow_raw_data["nodes"]) == 3
51
-
52
- # AND each node should be serialized correctly
53
- entrypoint_node = workflow_raw_data["nodes"][0]
54
- assert entrypoint_node == {
55
- "id": "09579c0a-acbf-4e04-8724-2230a8aa6534",
56
- "type": "ENTRYPOINT",
57
- "inputs": [],
58
- "data": {"label": "Entrypoint Node", "source_handle_id": "34069190-0942-4e0c-8700-b33b9dea4ea0"},
59
- "display_data": {"position": {"x": 0.0, "y": -50.0}},
60
- "base": None,
61
- "definition": None,
62
- }
63
50
 
64
- templating_node = workflow_raw_data["nodes"][1]
65
- assert not DeepDiff(
66
- {
67
- "id": "28ac8611-a755-4d8a-a5c3-520ddd119cf8",
68
- "type": "TEMPLATING",
69
- "inputs": [
70
- {
71
- "id": "7ceb3528-49c6-4f90-b3ef-92b1921a1b7d",
72
- "key": "template",
73
- "value": {
74
- "rules": [
75
- {
76
- "type": "CONSTANT_VALUE",
77
- "data": {"type": "STRING", "value": "The meaning of {{ info }} is not known"},
78
- }
79
- ],
80
- "combinator": "OR",
81
- },
82
- },
83
- {
84
- "id": "f46b5986-74f1-4ad4-b4d1-b8d2df6bc86f",
85
- "key": "info",
86
- "value": {
87
- "rules": [
88
- {
89
- "type": "INPUT_VARIABLE",
90
- "data": {"input_variable_id": "f4435f88-703f-40e5-9197-d39b0e43ab72"},
91
- }
92
- ],
93
- "combinator": "OR",
94
- },
95
- },
96
- ],
97
- "data": {
98
- "label": "Example Templating Node",
99
- "output_id": "076becd5-f282-40c5-9917-61099e114298",
100
- "error_output_id": None,
101
- "source_handle_id": "90a2ea33-b08d-46ec-8d9e-612592764268",
102
- "target_handle_id": "a215a440-cbd9-48ae-a831-be8fa78530a6",
103
- "template_node_input_id": "7ceb3528-49c6-4f90-b3ef-92b1921a1b7d",
104
- "output_type": "JSON",
105
- },
106
- "display_data": {"position": {"x": 200.0, "y": -50.0}},
107
- "base": {
108
- "name": "TemplatingNode",
109
- "module": ["vellum", "workflows", "nodes", "core", "templating_node", "node"],
110
- },
111
- "definition": {
112
- "name": "ExampleTemplatingNode",
113
- "module": ["tests", "workflows", "basic_templating_node", "workflow_with_json_input"],
114
- },
115
- "trigger": {
116
- "id": "a215a440-cbd9-48ae-a831-be8fa78530a6",
117
- "merge_behavior": "AWAIT_ATTRIBUTES",
118
- },
119
- "ports": [{"id": "90a2ea33-b08d-46ec-8d9e-612592764268", "name": "default", "type": "DEFAULT"}],
120
- },
121
- templating_node,
51
+ # AND the templating node should be serialized correctly
52
+ templating_node = next(
53
+ n for n in workflow_raw_data["nodes"] if (n.get("base") or {}).get("name") == "TemplatingNode"
122
54
  )
123
55
 
124
- final_output_node = workflow_raw_data["nodes"][-1]
125
- assert not DeepDiff(
126
- {
127
- "id": "9f75228b-1d5b-4c30-a581-6087e6a1b738",
128
- "type": "TERMINAL",
129
- "data": {
130
- "label": "Final Output",
131
- "name": "result",
132
- "target_handle_id": "16ba108e-61a8-4338-8a5b-4f1278d7fd7b",
133
- "output_id": "62ec9b08-6437-4f8d-bc20-983d317bc348",
134
- "output_type": "JSON",
135
- "node_input_id": "da51bb91-227c-481c-84d7-69c64322b485",
136
- },
137
- "inputs": [
138
- {
139
- "id": "da51bb91-227c-481c-84d7-69c64322b485",
140
- "key": "node_input",
141
- "value": {
142
- "rules": [
143
- {
144
- "type": "NODE_OUTPUT",
145
- "data": {
146
- "node_id": "28ac8611-a755-4d8a-a5c3-520ddd119cf8",
147
- "output_id": "076becd5-f282-40c5-9917-61099e114298",
148
- },
149
- }
150
- ],
151
- "combinator": "OR",
152
- },
153
- }
154
- ],
155
- "display_data": {"position": {"x": 400.0, "y": -50.0}},
156
- "base": {
157
- "name": "FinalOutputNode",
158
- "module": ["vellum", "workflows", "nodes", "displayable", "final_output_node", "node"],
159
- },
160
- "definition": None,
161
- },
162
- final_output_node,
163
- ignore_order=True,
164
- )
56
+ assert templating_node["id"] == "28ac8611-a755-4d8a-a5c3-520ddd119cf8"
57
+ assert templating_node["type"] == "TEMPLATING"
165
58
 
166
- # AND each edge should be serialized correctly
167
- serialized_edges = workflow_raw_data["edges"]
168
- assert not DeepDiff(
169
- [
170
- {
171
- "id": "7f26b32f-defb-4a2a-8656-c719fc9996a8",
172
- "source_node_id": "09579c0a-acbf-4e04-8724-2230a8aa6534",
173
- "source_handle_id": "34069190-0942-4e0c-8700-b33b9dea4ea0",
174
- "target_node_id": "28ac8611-a755-4d8a-a5c3-520ddd119cf8",
175
- "target_handle_id": "a215a440-cbd9-48ae-a831-be8fa78530a6",
176
- "type": "DEFAULT",
177
- },
178
- {
179
- "id": "00cbff5c-5cce-4ef4-81b2-1a11d9b42597",
180
- "source_node_id": "28ac8611-a755-4d8a-a5c3-520ddd119cf8",
181
- "source_handle_id": "90a2ea33-b08d-46ec-8d9e-612592764268",
182
- "target_node_id": "9f75228b-1d5b-4c30-a581-6087e6a1b738",
183
- "target_handle_id": "16ba108e-61a8-4338-8a5b-4f1278d7fd7b",
184
- "type": "DEFAULT",
185
- },
186
- ],
187
- serialized_edges,
188
- ignore_order=True,
189
- )
59
+ assert templating_node["base"]["name"] == "TemplatingNode"
60
+ assert templating_node["base"]["module"] == ["vellum", "workflows", "nodes", "core", "templating_node", "node"]
190
61
 
191
- # AND the display data should be what we expect
192
- display_data = workflow_raw_data["display_data"]
193
- assert display_data == {
194
- "viewport": {
195
- "x": 0.0,
196
- "y": 0.0,
197
- "zoom": 1.0,
198
- }
199
- }
62
+ assert templating_node["definition"]["name"] == "ExampleTemplatingNode"
63
+ assert templating_node["definition"]["module"] == [
64
+ "tests",
65
+ "workflows",
66
+ "basic_templating_node",
67
+ "workflow_with_json_input",
68
+ ]
69
+
70
+ assert templating_node["trigger"]["id"] == "a215a440-cbd9-48ae-a831-be8fa78530a6"
71
+ assert templating_node["trigger"]["merge_behavior"] == "AWAIT_ATTRIBUTES"
72
+
73
+ assert len(templating_node["ports"]) == 1
74
+ assert templating_node["ports"][0]["name"] == "default"
75
+ assert templating_node["ports"][0]["type"] == "DEFAULT"
76
+
77
+ assert templating_node["data"]["label"] == "Example Templating Node"
78
+ assert templating_node["data"]["output_id"] == "076becd5-f282-40c5-9917-61099e114298"
79
+ assert templating_node["data"]["error_output_id"] is None
80
+ assert templating_node["data"]["source_handle_id"] == "90a2ea33-b08d-46ec-8d9e-612592764268"
81
+ assert templating_node["data"]["target_handle_id"] == "a215a440-cbd9-48ae-a831-be8fa78530a6"
82
+ assert templating_node["data"]["template_node_input_id"] == "7ceb3528-49c6-4f90-b3ef-92b1921a1b7d"
83
+ assert templating_node["data"]["output_type"] == "JSON"
84
+
85
+ input_keys = {inp["key"] for inp in templating_node["inputs"]}
86
+ assert "template" in input_keys
87
+ assert "info" in input_keys
200
88
 
201
89
  # AND the definition should be what we expect
202
90
  definition = workflow_raw_data["definition"]
@@ -28,6 +28,7 @@ def test_serialize_workflow():
28
28
  "required": True,
29
29
  "default": None,
30
30
  "extensions": {"color": None},
31
+ "schema": {"type": "string"},
31
32
  }
32
33
  ]
33
34
 
@@ -101,6 +102,7 @@ def test_serialize_workflow():
101
102
  "name": "value",
102
103
  "type": "STRING",
103
104
  "value": {"type": "WORKFLOW_INPUT", "input_variable_id": "e39a7b63-de15-490a-ae9b-8112c767aea0"},
105
+ "schema": {"type": "string"},
104
106
  }
105
107
  ],
106
108
  "trigger": {
@@ -28,7 +28,7 @@ def test_serialize_workflow():
28
28
  output_variables = serialized_workflow["output_variables"]
29
29
  assert len(output_variables) == 2
30
30
 
31
- # Find the text and chat_history outputs
31
+ # Find the text and chat_history outputs (json is not exposed as workflow output)
32
32
  text_output = next(var for var in output_variables if var["key"] == "text")
33
33
  chat_history_output = next(var for var in output_variables if var["key"] == "chat_history")
34
34
 
@@ -80,8 +80,10 @@ def test_serialize_workflow():
80
80
 
81
81
  # AND the outputs should be correct
82
82
  outputs = tool_calling_node["outputs"]
83
- assert len(outputs) == 2
84
- assert outputs[0]["name"] == "text"
85
- assert outputs[0]["type"] == "STRING"
86
- assert outputs[1]["name"] == "chat_history"
87
- assert outputs[1]["type"] == "CHAT_HISTORY"
83
+ assert len(outputs) == 3
84
+ json_output = next(o for o in outputs if o["name"] == "json")
85
+ text_output = next(o for o in outputs if o["name"] == "text")
86
+ chat_history_output = next(o for o in outputs if o["name"] == "chat_history")
87
+ assert json_output["type"] == "JSON"
88
+ assert text_output["type"] == "STRING"
89
+ assert chat_history_output["type"] == "CHAT_HISTORY"