vellum-ai 1.7.6__py3-none-any.whl → 1.7.7__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.
@@ -27,10 +27,10 @@ class BaseClientWrapper:
27
27
 
28
28
  def get_headers(self) -> typing.Dict[str, str]:
29
29
  headers: typing.Dict[str, str] = {
30
- "User-Agent": "vellum-ai/1.7.6",
30
+ "User-Agent": "vellum-ai/1.7.7",
31
31
  "X-Fern-Language": "Python",
32
32
  "X-Fern-SDK-Name": "vellum-ai",
33
- "X-Fern-SDK-Version": "1.7.6",
33
+ "X-Fern-SDK-Version": "1.7.7",
34
34
  **(self.get_custom_headers() or {}),
35
35
  }
36
36
  if self._api_version is not None:
@@ -1,10 +1,12 @@
1
1
  from abc import ABC
2
- from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Tuple, Type
2
+ from uuid import UUID
3
+ from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Set, Tuple, Type
3
4
 
4
5
  from vellum.workflows.inputs.base import BaseInputs
5
6
  from vellum.workflows.nodes.bases.base import BaseNode, BaseNodeMeta
6
7
  from vellum.workflows.outputs.base import BaseOutputs
7
8
  from vellum.workflows.references.output import OutputReference
9
+ from vellum.workflows.types.core import MergeBehavior
8
10
  from vellum.workflows.types.generics import StateType
9
11
 
10
12
  if TYPE_CHECKING:
@@ -79,6 +81,56 @@ class BaseAdornmentNode(
79
81
  __wrapped_node__: Optional[Type["BaseNode"]] = None
80
82
  subworkflow: Type["BaseWorkflow"]
81
83
 
84
+ class Trigger(BaseNode.Trigger):
85
+ """
86
+ Trigger class for adornment nodes that delegates to the wrapped node's Trigger
87
+ for proper merge behavior handling.
88
+ """
89
+
90
+ @classmethod
91
+ def should_initiate(
92
+ cls,
93
+ state: StateType,
94
+ dependencies: Set["Type[BaseNode]"],
95
+ node_span_id: UUID,
96
+ ) -> bool:
97
+ """
98
+ Delegates to the wrapped node's Trigger.should_initiate method to ensure
99
+ proper merge behavior (like AWAIT_ALL) is respected for initiation logic.
100
+ """
101
+ # Get the wrapped node's Trigger class
102
+ wrapped_node = cls.node_class.__wrapped_node__
103
+ if wrapped_node is not None:
104
+ wrapped_trigger = wrapped_node.Trigger
105
+ # Only delegate if the wrapped node has a specific merge behavior
106
+ # that differs from the default AWAIT_ATTRIBUTES
107
+ if (
108
+ hasattr(wrapped_trigger, "merge_behavior")
109
+ and wrapped_trigger.merge_behavior != MergeBehavior.AWAIT_ATTRIBUTES
110
+ ):
111
+ return wrapped_trigger.should_initiate(state, dependencies, node_span_id)
112
+
113
+ # Fallback to the base implementation if no wrapped node
114
+ return super().should_initiate(state, dependencies, node_span_id)
115
+
116
+ @classmethod
117
+ def _queue_node_execution(
118
+ cls, state: StateType, dependencies: set[Type[BaseNode]], invoked_by: Optional[UUID] = None
119
+ ) -> UUID:
120
+ """
121
+ Delegates to the wrapped node's Trigger._queue_node_execution method to ensure
122
+ proper merge behavior (like AWAIT_ALL) is respected for dependency tracking.
123
+ """
124
+ # Get the wrapped node's Trigger class
125
+ wrapped_node = cls.node_class.__wrapped_node__
126
+ if wrapped_node is not None:
127
+ wrapped_trigger = wrapped_node.Trigger
128
+ # Delegate to the wrapped node's trigger logic for queuing
129
+ return wrapped_trigger._queue_node_execution(state, dependencies, invoked_by)
130
+
131
+ # Fallback to the base implementation if no wrapped node
132
+ return super()._queue_node_execution(state, dependencies, invoked_by)
133
+
82
134
  @classmethod
83
135
  def __annotate_outputs_class__(cls, outputs_class: Type[BaseOutputs], reference: OutputReference) -> None:
84
136
  # Subclasses of BaseAdornableNode can override this method to provider their own
@@ -7,6 +7,7 @@ from vellum import (
7
7
  AdHocExpandMeta,
8
8
  ChatMessage,
9
9
  FunctionDefinition,
10
+ InitiatedAdHocExecutePromptEvent,
10
11
  PromptBlock,
11
12
  PromptOutput,
12
13
  PromptParameters,
@@ -185,7 +186,8 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
185
186
  expand_meta=self.expand_meta,
186
187
  request_options=request_options,
187
188
  )
188
- return iter([response])
189
+ initiated_event = InitiatedAdHocExecutePromptEvent(execution_id=response.execution_id)
190
+ return iter([initiated_event, response])
189
191
  else:
190
192
  return self._context.vellum_client.ad_hoc.adhoc_execute_prompt_stream(
191
193
  ml_model=self.ml_model,
@@ -724,22 +724,24 @@ class WorkflowRunner(Generic[StateType]):
724
724
  parent_context: The parent context for the cancellation events
725
725
  """
726
726
  captured_stacktrace = "".join(traceback.format_stack())
727
- for span_id, active_node in list(self._active_nodes_by_execution_id.items()):
728
- rejection_event = NodeExecutionRejectedEvent(
729
- trace_id=self._execution_context.trace_id,
730
- span_id=span_id,
731
- body=NodeExecutionRejectedBody(
732
- node_definition=active_node.node.__class__,
733
- error=WorkflowError(
734
- code=WorkflowErrorCode.NODE_CANCELLED,
735
- message=error_message,
727
+ active_span_ids = list(self._active_nodes_by_execution_id.keys())
728
+ for span_id in active_span_ids:
729
+ active_node = self._active_nodes_by_execution_id.pop(span_id, None)
730
+ if active_node is not None:
731
+ rejection_event = NodeExecutionRejectedEvent(
732
+ trace_id=self._execution_context.trace_id,
733
+ span_id=span_id,
734
+ body=NodeExecutionRejectedBody(
735
+ node_definition=active_node.node.__class__,
736
+ error=WorkflowError(
737
+ code=WorkflowErrorCode.NODE_CANCELLED,
738
+ message=error_message,
739
+ ),
740
+ stacktrace=captured_stacktrace,
736
741
  ),
737
- stacktrace=captured_stacktrace,
738
- ),
739
- parent=parent_context,
740
- )
741
- self._workflow_event_outer_queue.put(rejection_event)
742
- self._active_nodes_by_execution_id.pop(span_id)
742
+ parent=parent_context,
743
+ )
744
+ self._workflow_event_outer_queue.put(rejection_event)
743
745
 
744
746
  def _initiate_workflow_event(self) -> WorkflowExecutionInitiatedEvent:
745
747
  links: Optional[List[SpanLink]] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 1.7.6
3
+ Version: 1.7.7
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -32,7 +32,7 @@ vellum_ee/workflows/display/editor/__init__.py,sha256=MSAgY91xCEg2neH5d8jXx5wRdR
32
32
  vellum_ee/workflows/display/editor/types.py,sha256=rmaNXkNZUNRgK-mJJ_g1-Fm3OGxoQfqEB7zn-zzgJtc,664
33
33
  vellum_ee/workflows/display/exceptions.py,sha256=_FDhK-lfuBPHY2GSywp70ewM0k55Ji5Bp-wZlEZenz4,112
34
34
  vellum_ee/workflows/display/nodes/__init__.py,sha256=jI1aPBQf8DkmrYoZ4O-wR1duqZByOf5mDFmo_wFJPE4,307
35
- vellum_ee/workflows/display/nodes/base_node_display.py,sha256=C0Dxwss5yoxSLotTRUP2h7oxGjb0dDIdsc-83HVFCP8,19493
35
+ vellum_ee/workflows/display/nodes/base_node_display.py,sha256=ceKQdHZmDSOY5-M2DtJnuLbdkuFujCChFtRABDoV1jo,19497
36
36
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=jI_kUi9LnNLDpY63QtlC4TfN8P571VN4LpzH0I1ZtLk,1149
37
37
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=JLa9nlG38dLfCo1Y8ISsJ21hrfDyy4-ae3pZ9H01yFs,5578
@@ -80,7 +80,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DE
80
80
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=Y-ajeT65b5varmrZCw6L3hir4hJCFq-eO0jZfRcrs7g,1886
82
82
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=wdVaFvxicj48Kj-6VUlu61KR0oSArLTjownRi2p0NWQ,14941
83
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=bPTwkLpB7trFLpAaDvXMfMP0c9H1u_c1cdnj7K-gtnw,24962
83
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=rDh6PxhdoVDNuKdUrtZpoMtX8T92ZUMonkVxDjeEE4g,25507
84
84
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=SwXRzjdoEZLvkzaRMvRV8_UqbBm0EB_UtAHD_zXKZBY,6303
85
85
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=jubGYgLJImOqILd5LjnYJ4B1UMIrToDrQbPZOvaQCX4,40035
86
86
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=FLvcD8eoABHUPv08oSpIp_P-65sw2gl4whMXEJJj4f8,6785
@@ -119,7 +119,7 @@ vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
119
119
  vellum_ee/workflows/display/utils/auto_layout.py,sha256=f4GiLn_LazweupfqTpubcdtdfE_vrOcmZudSsnYIY9E,3906
120
120
  vellum_ee/workflows/display/utils/events.py,sha256=DE33uoKW78BZtITJ6L22dMZN3KR1BuZBVC98C_gIyzU,1943
121
121
  vellum_ee/workflows/display/utils/exceptions.py,sha256=E8Lvo7LY1BoZ54M_NR_opDjJsAAiCUfow1HgoHcTHmg,989
122
- vellum_ee/workflows/display/utils/expressions.py,sha256=mg-AHKGvnRjB1y4nXFJp7uRuAkUGITnuZ6aRDnEzPXk,20512
122
+ vellum_ee/workflows/display/utils/expressions.py,sha256=IIieWILv2zGLYTRgeDwgjhtga1ttV-ss2remJ1HBVXA,20688
123
123
  vellum_ee/workflows/display/utils/registry.py,sha256=1qXiBTdsnro6FeCX0FGBEK7CIf6wa--Jt50iZ_nEp_M,3460
124
124
  vellum_ee/workflows/display/utils/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  vellum_ee/workflows/display/utils/tests/test_auto_layout.py,sha256=vfXI769418s9vda5Gb5NFBH747WMOwSgHRXeLCTLVm8,2356
@@ -161,7 +161,7 @@ vellum/client/README.md,sha256=flqu57ubZNTfpq60CdLtJC9gp4WEkyjb_n_eZ4OYf9w,6497
161
161
  vellum/client/__init__.py,sha256=rMnKRqL5-356SBc-rfm56MkO87PuAi2mtcfBszcJU1M,74316
162
162
  vellum/client/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
163
163
  vellum/client/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
164
- vellum/client/core/client_wrapper.py,sha256=Xg-fX0-gnXrGKMqx9QTWnqutz2unMYFhgA34qo_877U,2840
164
+ vellum/client/core/client_wrapper.py,sha256=A3sL2WdcS11xGFV5Yq5h9yzf-96DpP7AL8dayvAKlUk,2840
165
165
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
166
166
  vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
167
167
  vellum/client/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
@@ -1886,7 +1886,7 @@ vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,4
1886
1886
  vellum/workflows/nodes/__init__.py,sha256=zymtc3_iW2rFmMR-sayTLuN6ZsAw8VnJweWPsjQk2-Q,1197
1887
1887
  vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
1888
1888
  vellum/workflows/nodes/bases/base.py,sha256=u7NmYWhQZm91KZV53PGD-gpZvcWAItOme95TjZkHwDI,22094
1889
- vellum/workflows/nodes/bases/base_adornment_node.py,sha256=hrgzuTetM4ynPd9YGHoK8Vwwn4XITi3aZZ_OCnQrq4Y,3433
1889
+ vellum/workflows/nodes/bases/base_adornment_node.py,sha256=TgL-tfX84GyTb7ONQ2z7OJDkx57kW3qbQNDuiw-Zrqo,5814
1890
1890
  vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1891
1891
  vellum/workflows/nodes/bases/tests/test_base_adornment_node.py,sha256=fXZI9KqpS4XMBrBnIEkK3foHaBVvyHwYcQWWDKay7ic,1148
1892
1892
  vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=igJrcSxSZADk5tLpssAt0uAXe9oJoLbilzueJJvA5p4,10942
@@ -1925,7 +1925,7 @@ vellum/workflows/nodes/displayable/bases/api_node/tests/test_node.py,sha256=5C59
1925
1925
  vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py,sha256=Org3xTvgp1pA0uUXFfnJr29D3HzCey2lEdYF4zbIUgo,70
1926
1926
  vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=w02vgydiwNoKru324QLSkH3BiGUvHTgKbf05BEx945s,4657
1927
1927
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py,sha256=Hl35IAoepRpE-j4cALaXVJIYTYOF3qszyVbxTj4kS1s,82
1928
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=Medz-nM5dqaaNRSPAJ0LUfnv4o57RGBwKFoYNAmCf48,18484
1928
+ vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=ITxAa1HWF6OPdcKg0DdTK7YP94ezzzWVyZzCRMiybIg,18638
1929
1929
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1930
1930
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py,sha256=xc53wGwVqxBnN7eoyWkJ-RJ-FeUpHKekkKjViASHAFg,27495
1931
1931
  vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=H9mM75EQpP6PUvsXCTbwjw4CqMMLf36m1G2XqiPEvH4,12139
@@ -2025,7 +2025,7 @@ vellum/workflows/resolvers/resolver.py,sha256=3uEYscB_2PHTazc0Y9SzOe_yiQZhVLfey1
2025
2025
  vellum/workflows/resolvers/tests/test_resolver.py,sha256=PnUGzsulo1It_LjjhHsRNiILvvl5G_IaK8ZX56zKC28,6204
2026
2026
  vellum/workflows/resolvers/types.py,sha256=Hndhlk69g6EKLh_LYg5ILepW5U_h_BYNllfzhS9k8p4,237
2027
2027
  vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
2028
- vellum/workflows/runner/runner.py,sha256=250GCJFyqTX9q5gYhfo6AkiIgMScVfEp4KYofRweqEk,45455
2028
+ vellum/workflows/runner/runner.py,sha256=IYjeFx6_jescg8tEW-et5k96X9EsB6PDw4Kw4Qvy-Xo,45599
2029
2029
  vellum/workflows/sandbox.py,sha256=mezSZmilR_fwR8164n8CEfzlMeQ55IqfapHp4ftImvQ,3212
2030
2030
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
2031
2031
  vellum/workflows/state/base.py,sha256=A8s0PC8UvFjPpkHDY6u-yIeb2KHjoAmu-GW-GYrDl0E,24654
@@ -2075,8 +2075,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
2075
2075
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2076
2076
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=Boa-_m9ii2Qsa1RvVM-VYniF7zCpzGgEGy-OnPZkrHg,23941
2077
2077
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
2078
- vellum_ai-1.7.6.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
2079
- vellum_ai-1.7.6.dist-info/METADATA,sha256=Bk9FFFzHL7vS59oSmxxgX_8fOxREGwYmlaqSFXP6zr4,5547
2080
- vellum_ai-1.7.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
2081
- vellum_ai-1.7.6.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
2082
- vellum_ai-1.7.6.dist-info/RECORD,,
2078
+ vellum_ai-1.7.7.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
2079
+ vellum_ai-1.7.7.dist-info/METADATA,sha256=AUowwbBfQrczLwFHQeRVeZoiVw6lIuKUlK52uh9Qb6o,5547
2080
+ vellum_ai-1.7.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
2081
+ vellum_ai-1.7.7.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
2082
+ vellum_ai-1.7.7.dist-info/RECORD,,
@@ -188,7 +188,7 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
188
188
  type = primitive_type_to_vellum_variable_type(output)
189
189
  value = (
190
190
  serialize_value(node_id, display_context, output.instance)
191
- if output.instance is not None and output.instance != undefined
191
+ if output.instance is not None and output.instance is not undefined
192
192
  else None
193
193
  )
194
194
 
@@ -688,3 +688,19 @@ def test_serialize_node__comment_expanded_preserved_when_explicitly_set(serializ
688
688
  assert "comment" in display_data
689
689
  assert display_data["comment"]["value"] == "This is a test comment."
690
690
  assert display_data["comment"]["expanded"] is False
691
+
692
+
693
+ def test_serialize_node__attribute_with_type_annotation_no_default(serialize_node):
694
+ """
695
+ Tests that attributes with type annotations but no default values serialize as None.
696
+ """
697
+
698
+ # GIVEN a node with typed attributes but no default values
699
+ class NodeWithTypedAttributesNoDefault(BaseNode):
700
+ attr: str
701
+
702
+ # WHEN the node is serialized
703
+ serialized_node = serialize_node(NodeWithTypedAttributesNoDefault)
704
+
705
+ # THEN the attribute should serialize as None
706
+ assert serialized_node["attributes"][0]["value"] is None
@@ -3,7 +3,7 @@ import inspect
3
3
  from io import StringIO
4
4
  import sys
5
5
  from uuid import UUID
6
- from typing import TYPE_CHECKING, Any, Dict, List, cast
6
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
7
7
 
8
8
  from pydantic import BaseModel
9
9
 
@@ -248,13 +248,11 @@ def serialize_key(key: Any) -> str:
248
248
  return str(key)
249
249
 
250
250
 
251
- # Sentinel value to indicate a value should be omitted from serialization
252
- _UNDEFINED_SENTINEL: JsonObject = {"__undefined__": True}
253
-
254
-
255
- def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContext", value: Any) -> JsonObject:
251
+ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContext", value: Any) -> Optional[JsonObject]:
256
252
  """
257
- Serialize a value to a JSON object.
253
+ Serialize a value to a JSON object. Returns `None` if the value resolves to `undefined`.
254
+ This is safe because all valid values are a JSON object, including the `None` constant:
255
+ > `{"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}}`
258
256
 
259
257
  Args:
260
258
  executable_id: node id or workflow id
@@ -265,7 +263,7 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
265
263
  serialized value
266
264
  """
267
265
  if value is undefined:
268
- return _UNDEFINED_SENTINEL
266
+ return None
269
267
 
270
268
  if isinstance(value, ConstantValueReference):
271
269
  return serialize_value(executable_id, display_context, value._value)
@@ -353,7 +351,7 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
353
351
  serialized_items = []
354
352
  for item in value:
355
353
  serialized_item = serialize_value(executable_id, display_context, item)
356
- if serialized_item != _UNDEFINED_SENTINEL:
354
+ if serialized_item is not None:
357
355
  serialized_items.append(serialized_item)
358
356
 
359
357
  if all(isinstance(item, dict) and item["type"] == "CONSTANT_VALUE" for item in serialized_items):
@@ -389,7 +387,7 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
389
387
  serialized_entries: List[Dict[str, Any]] = []
390
388
  for key, val in value.items():
391
389
  serialized_val = serialize_value(executable_id, display_context, val)
392
- if serialized_val != _UNDEFINED_SENTINEL:
390
+ if serialized_val is not None:
393
391
  serialized_entries.append(
394
392
  {
395
393
  "id": str(uuid4_from_hash(f"{executable_id}|{key}")),
@@ -455,7 +453,9 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
455
453
  if inputs:
456
454
  serialized_inputs = {}
457
455
  for param_name, input_ref in inputs.items():
458
- serialized_inputs[param_name] = serialize_value(executable_id, display_context, input_ref)
456
+ serialized_input = serialize_value(executable_id, display_context, input_ref)
457
+ if serialized_input is not None:
458
+ serialized_inputs[param_name] = serialized_input
459
459
 
460
460
  model_data = function_definition.model_dump()
461
461
  model_data["inputs"] = serialized_inputs