vellum-ai 1.8.5__py3-none-any.whl → 1.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. vellum/__init__.py +6 -0
  2. vellum/client/core/client_wrapper.py +2 -2
  3. vellum/client/types/__init__.py +6 -0
  4. vellum/client/types/api_actor_type_enum.py +7 -0
  5. vellum/client/types/api_request_parent_context.py +6 -0
  6. vellum/client/types/external_parent_context.py +2 -0
  7. vellum/client/types/integration_name.py +1 -0
  8. vellum/client/types/integration_trigger_context.py +38 -0
  9. vellum/client/types/node_execution_fulfilled_event.py +2 -0
  10. vellum/client/types/node_execution_initiated_event.py +2 -0
  11. vellum/client/types/node_execution_paused_event.py +2 -0
  12. vellum/client/types/node_execution_rejected_event.py +2 -0
  13. vellum/client/types/node_execution_resumed_event.py +2 -0
  14. vellum/client/types/node_execution_span.py +2 -0
  15. vellum/client/types/node_execution_streaming_event.py +2 -0
  16. vellum/client/types/node_parent_context.py +2 -0
  17. vellum/client/types/parent_context.py +4 -0
  18. vellum/client/types/prompt_deployment_parent_context.py +2 -0
  19. vellum/client/types/scheduled_trigger_context.py +38 -0
  20. vellum/client/types/slim_workflow_execution_read.py +2 -0
  21. vellum/client/types/span_link.py +2 -0
  22. vellum/client/types/workflow_deployment_event_executions_response.py +2 -0
  23. vellum/client/types/workflow_deployment_parent_context.py +2 -0
  24. vellum/client/types/workflow_event_execution_read.py +2 -0
  25. vellum/client/types/workflow_execution_detail.py +2 -0
  26. vellum/client/types/workflow_execution_fulfilled_event.py +2 -0
  27. vellum/client/types/workflow_execution_initiated_event.py +2 -0
  28. vellum/client/types/workflow_execution_paused_event.py +2 -0
  29. vellum/client/types/workflow_execution_rejected_event.py +2 -0
  30. vellum/client/types/workflow_execution_resumed_event.py +2 -0
  31. vellum/client/types/workflow_execution_snapshotted_event.py +2 -0
  32. vellum/client/types/workflow_execution_span.py +2 -0
  33. vellum/client/types/workflow_execution_streaming_event.py +2 -0
  34. vellum/client/types/workflow_parent_context.py +2 -0
  35. vellum/client/types/workflow_sandbox_parent_context.py +2 -0
  36. vellum/types/api_actor_type_enum.py +3 -0
  37. vellum/types/integration_trigger_context.py +3 -0
  38. vellum/types/scheduled_trigger_context.py +3 -0
  39. vellum/workflows/inputs/dataset_row.py +9 -7
  40. vellum/workflows/nodes/displayable/final_output_node/node.py +4 -0
  41. vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py +28 -0
  42. vellum/workflows/nodes/displayable/set_state_node/__init__.py +5 -0
  43. vellum/workflows/nodes/displayable/set_state_node/node.py +71 -0
  44. vellum/workflows/nodes/displayable/set_state_node/tests/__init__.py +0 -0
  45. vellum/workflows/nodes/displayable/set_state_node/tests/test_node.py +212 -0
  46. vellum/workflows/sandbox.py +13 -3
  47. vellum/workflows/tests/test_dataset_row.py +20 -0
  48. vellum/workflows/tests/test_sandbox.py +40 -0
  49. vellum/workflows/tests/triggers/{test_vellum_integration_trigger.py → test_integration_trigger.py} +22 -22
  50. vellum/workflows/triggers/__init__.py +2 -2
  51. vellum/workflows/triggers/base.py +22 -4
  52. vellum/workflows/triggers/integration.py +168 -49
  53. vellum/workflows/triggers/schedule.py +18 -0
  54. vellum/workflows/triggers/tests/test_integration.py +49 -20
  55. vellum/workflows/utils/uuids.py +1 -15
  56. vellum/workflows/workflows/base.py +44 -0
  57. {vellum_ai-1.8.5.dist-info → vellum_ai-1.9.0.dist-info}/METADATA +1 -1
  58. {vellum_ai-1.8.5.dist-info → vellum_ai-1.9.0.dist-info}/RECORD +67 -57
  59. vellum_ee/workflows/display/tests/workflow_serialization/{test_vellum_integration_trigger_serialization.py → test_integration_trigger_serialization.py} +8 -8
  60. vellum_ee/workflows/display/utils/expressions.py +2 -3
  61. vellum_ee/workflows/display/workflows/base_workflow_display.py +9 -9
  62. vellum_ee/workflows/server/virtual_file_loader.py +74 -2
  63. vellum_ee/workflows/tests/test_server.py +81 -66
  64. vellum_ee/workflows/tests/test_virtual_files.py +48 -0
  65. vellum/workflows/triggers/vellum_integration.py +0 -189
  66. {vellum_ai-1.8.5.dist-info → vellum_ai-1.9.0.dist-info}/LICENSE +0 -0
  67. {vellum_ai-1.8.5.dist-info → vellum_ai-1.9.0.dist-info}/WHEEL +0 -0
  68. {vellum_ai-1.8.5.dist-info → vellum_ai-1.9.0.dist-info}/entry_points.txt +0 -0
@@ -1,67 +1,186 @@
1
1
  from abc import ABC
2
- from typing import ClassVar, Optional
2
+ from typing import Any, ClassVar, Dict
3
3
 
4
- from vellum.workflows.triggers.base import BaseTrigger
4
+ from vellum.workflows.constants import VellumIntegrationProviderType
5
+ from vellum.workflows.references.trigger import TriggerAttributeReference
6
+ from vellum.workflows.triggers.base import BaseTrigger, BaseTriggerMeta
5
7
 
6
8
 
7
- class IntegrationTrigger(BaseTrigger, ABC):
9
+ class IntegrationTriggerMeta(BaseTriggerMeta):
8
10
  """
9
- Base class for integration-based triggers (Slack, Email, etc.).
11
+ Custom metaclass for IntegrationTrigger.
10
12
 
11
- Integration triggers:
12
- - Are initiated by external events (webhooks, API calls)
13
- - Produce attributes that downstream nodes can reference
14
- - Require configuration (auth, webhooks, etc.)
13
+ This metaclass extends BaseTriggerMeta to automatically convert type annotations
14
+ into TriggerAttributeReference objects during class creation. This enables trigger
15
+ attributes to be referenced in workflow graphs while maintaining type safety.
16
+ """
17
+
18
+ def __new__(mcs, name: str, bases: tuple, namespace: dict, **kwargs: Any) -> "IntegrationTriggerMeta":
19
+ """Create a new trigger class and set up attribute references."""
20
+ cls = super().__new__(mcs, name, bases, namespace, **kwargs)
21
+
22
+ # Process __annotations__ to create TriggerAttributeReference for each attribute
23
+ # Only process if class has Config and annotations
24
+ has_config = hasattr(cls, "Config") and "Config" in namespace
25
+ if has_config and hasattr(cls, "__annotations__"):
26
+ # Create TriggerAttributeReference for each annotated attribute
27
+ for attr_name, attr_type in cls.__annotations__.items():
28
+ # Skip special attributes and Config
29
+ if attr_name.startswith("_") or attr_name == "Config":
30
+ continue
31
+
32
+ # Create reference with proper type
33
+ reference = TriggerAttributeReference(
34
+ name=attr_name, types=(attr_type,), instance=None, trigger_class=cls
35
+ )
36
+ # Set as class attribute so it's directly accessible
37
+ setattr(cls, attr_name, reference)
38
+
39
+ return cls
40
+
41
+
42
+ class IntegrationTrigger(BaseTrigger, ABC, metaclass=IntegrationTriggerMeta):
43
+ """
44
+ Base class for Vellum-managed integration triggers.
45
+
46
+ Subclasses define two types of attributes:
47
+ 1. **Config class**: Specifies how the trigger is configured (provider, integration_name, slug)
48
+ - These are configuration details users shouldn't need to interact with directly
49
+ 2. **Top-level type annotations**: Define the webhook event payload structure (message, user, channel, etc.)
50
+ - These become TriggerAttributeReference that can be referenced in workflow nodes
15
51
 
16
52
  Examples:
17
- # Define an integration trigger
18
- class MyIntegrationTrigger(IntegrationTrigger):
19
- data: str
20
-
21
- def __init__(self, event_data: dict):
22
- super().__init__(event_data)
23
- self.data = event_data.get("data", "")
24
-
25
- # Use in workflow
26
- class MyWorkflow(BaseWorkflow):
27
- graph = MyIntegrationTrigger >> ProcessNode
28
-
29
- # Reference trigger attributes in nodes
30
- class ProcessNode(BaseNode):
31
- class Outputs(BaseNode.Outputs):
32
- result = MyIntegrationTrigger.data
33
-
34
- Note:
35
- Unlike ManualTrigger, integration triggers provide structured attributes
36
- that downstream nodes can reference directly.
53
+ Create a Slack trigger:
54
+ >>> class SlackNewMessageTrigger(IntegrationTrigger):
55
+ ... # Event attributes (webhook payload structure)
56
+ ... message: str
57
+ ... user: str
58
+ ... channel: str
59
+ ... timestamp: float
60
+ ...
61
+ ... # Configuration (how trigger is set up)
62
+ ... class Config(IntegrationTrigger.Config):
63
+ ... provider = VellumIntegrationProviderType.COMPOSIO
64
+ ... integration_name = "SLACK"
65
+ ... slug = "slack_new_message"
66
+
67
+ Use in workflow graph:
68
+ >>> class MyWorkflow(BaseWorkflow):
69
+ ... graph = SlackNewMessageTrigger >> ProcessMessageNode
70
+
71
+ Reference trigger attributes in nodes:
72
+ >>> class ProcessNode(BaseNode):
73
+ ... class Outputs(BaseNode.Outputs):
74
+ ... text = SlackNewMessageTrigger.message
75
+ ... channel = SlackNewMessageTrigger.channel
76
+
77
+ Instantiate for testing:
78
+ >>> trigger = SlackNewMessageTrigger(
79
+ ... message="Hello world",
80
+ ... channel="C123456",
81
+ ... user="U123",
82
+ ... timestamp=1234567890.0,
83
+ ... )
84
+ >>> trigger.message
85
+ 'Hello world'
37
86
  """
38
87
 
39
- # Configuration that can be set at runtime
40
- config: ClassVar[Optional[dict]] = None
88
+ class Config:
89
+ """
90
+ Configuration for IntegrationTrigger subclasses.
41
91
 
42
- def __init__(self, event_data: dict):
92
+ Defines how the trigger connects to the integration provider. These settings
93
+ specify which integration and which specific trigger type to use.
43
94
  """
44
- Initialize trigger with event data from external system.
45
95
 
46
- Subclasses should override this method to parse external
47
- event payloads (e.g., Slack webhooks, email notifications) and
48
- populate trigger attributes.
96
+ provider: ClassVar[VellumIntegrationProviderType]
97
+ integration_name: ClassVar[str]
98
+ slug: ClassVar[str]
49
99
 
50
- Args:
51
- event_data: Raw event data from the external system
100
+ def __init_subclass__(cls, **kwargs: Any) -> None:
101
+ """Validate that subclasses define required Config class with all required fields."""
102
+ super().__init_subclass__(**kwargs)
103
+
104
+ # Skip validation for the base class itself
105
+ if cls.__name__ == "IntegrationTrigger":
106
+ return
107
+
108
+ # Require Config class with required fields
109
+ if not hasattr(cls, "Config") or cls.Config is IntegrationTrigger.Config:
110
+ raise TypeError(
111
+ f"{cls.__name__} must define a nested Config class. "
112
+ f"Example:\n"
113
+ f" class {cls.__name__}(IntegrationTrigger):\n"
114
+ f" message: str\n"
115
+ f" class Config(IntegrationTrigger.Config):\n"
116
+ f" provider = VellumIntegrationProviderType.COMPOSIO\n"
117
+ f" integration_name = 'SLACK'\n"
118
+ f" slug = 'slack_new_message'"
119
+ )
120
+
121
+ # Validate Config class has required fields
122
+ config_cls = cls.Config
123
+ required_fields = ["provider", "integration_name", "slug"]
124
+ for field in required_fields:
125
+ if not hasattr(config_cls, field):
126
+ raise TypeError(
127
+ f"{cls.__name__}.Config must define '{field}'. " f"Required fields: {', '.join(required_fields)}"
128
+ )
129
+
130
+ def __init__(self, **kwargs: Any):
131
+ """
132
+ Initialize trigger with event data from the integration.
133
+
134
+ The trigger dynamically populates its attributes based on the kwargs
135
+ dictionary keys. Any key in kwargs becomes an accessible attribute.
52
136
 
53
137
  Examples:
54
- >>> class MyTrigger(IntegrationTrigger):
55
- ... data: str
138
+ >>> class SlackTrigger(IntegrationTrigger):
139
+ ... message: str
140
+ ... channel: str
141
+ ... user: str
56
142
  ...
57
- ... def __init__(self, event_data: dict):
58
- ... super().__init__(event_data)
59
- ... self.data = event_data.get("data", "")
60
- >>>
61
- >>> trigger = MyTrigger({"data": "hello"})
62
- >>> state = workflow.get_default_state()
63
- >>> trigger.bind_to_state(state)
64
- >>> MyTrigger.data.resolve(state)
65
- 'hello'
143
+ ... class Config(IntegrationTrigger.Config):
144
+ ... provider = VellumIntegrationProviderType.COMPOSIO
145
+ ... integration_name = "SLACK"
146
+ ... slug = "slack_new_message"
147
+ >>> trigger = SlackTrigger(
148
+ ... message="Hello",
149
+ ... channel="C123",
150
+ ... user="U456"
151
+ ... )
152
+ >>> trigger.message
153
+ 'Hello'
154
+ >>> trigger.channel
155
+ 'C123'
66
156
  """
67
- self._event_data = event_data
157
+ super().__init__(**kwargs)
158
+
159
+ # Dynamically populate instance attributes from kwargs.
160
+ # This allows any key in kwargs to become an accessible attribute:
161
+ # kwargs={"message": "Hi"} → trigger.message == "Hi"
162
+ for key, value in kwargs.items():
163
+ setattr(self, key, value)
164
+
165
+ def to_trigger_attribute_values(self) -> Dict["TriggerAttributeReference[Any]", Any]:
166
+ """
167
+ Materialize attribute descriptor/value pairs for this trigger instance.
168
+
169
+ For IntegrationTrigger, this includes all dynamic attributes from event_data.
170
+ """
171
+ attribute_values: Dict["TriggerAttributeReference[Any]", Any] = {}
172
+
173
+ # Unlike the base class which iterates over type(self) (predefined annotations),
174
+ # we iterate over event_data keys since our attributes are discovered dynamically
175
+ # from the actual event data received during workflow execution.
176
+ # The base class approach: for reference in type(self)
177
+ # Our approach: for attr_name in self._event_data.keys()
178
+ for attr_name in self._event_data.keys():
179
+ # Get the class-level reference for this attribute (created by __new__ from annotations)
180
+ # Unknown keys can appear in webhook payloads, so gracefully skip them if the
181
+ # trigger class doesn't expose a corresponding reference.
182
+ reference = getattr(type(self), attr_name, None)
183
+ if isinstance(reference, TriggerAttributeReference):
184
+ attribute_values[reference] = getattr(self, attr_name)
185
+
186
+ return attribute_values
@@ -0,0 +1,18 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from vellum.workflows.triggers.base import BaseTrigger
5
+
6
+
7
+ class ScheduleTrigger(BaseTrigger):
8
+ """
9
+ Trigger representing time-based workflow invocation.
10
+ Supports Cron-based schedules (e.g., "0 9 * * MON" for every Monday at 9am)
11
+ """
12
+
13
+ current_run_at: datetime
14
+ next_run_at: datetime
15
+
16
+ class Config:
17
+ cron: str
18
+ timezone: Optional[str] = None
@@ -1,5 +1,8 @@
1
1
  """Tests for IntegrationTrigger base class."""
2
2
 
3
+ from typing import Any
4
+
5
+ from vellum.workflows.constants import VellumIntegrationProviderType
3
6
  from vellum.workflows.nodes.bases.base import BaseNode
4
7
  from vellum.workflows.references.trigger import TriggerAttributeReference
5
8
  from vellum.workflows.state.base import BaseState
@@ -9,7 +12,7 @@ from vellum.workflows.triggers.integration import IntegrationTrigger
9
12
  def test_integration_trigger__can_be_instantiated_as_base():
10
13
  """IntegrationTrigger can be instantiated as a base class."""
11
14
  # WHEN we instantiate IntegrationTrigger directly
12
- trigger = IntegrationTrigger({"test": "data"})
15
+ trigger = IntegrationTrigger(test="data")
13
16
 
14
17
  # THEN it creates an instance with event data stored
15
18
  assert trigger._event_data == {"test": "data"}
@@ -20,7 +23,10 @@ def test_integration_trigger__can_be_instantiated():
20
23
 
21
24
  # GIVEN IntegrationTrigger with concrete implementation
22
25
  class TestTrigger(IntegrationTrigger):
23
- pass
26
+ class Config(IntegrationTrigger.Config):
27
+ provider = VellumIntegrationProviderType.COMPOSIO
28
+ integration_name = "test"
29
+ slug = "test"
24
30
 
25
31
  # THEN it can be instantiated (even though base is ABC, concrete subclasses work)
26
32
  assert TestTrigger is not None
@@ -33,12 +39,17 @@ def test_integration_trigger__can_be_subclassed():
33
39
  class TestTrigger(IntegrationTrigger):
34
40
  data: str
35
41
 
36
- def __init__(self, event_data: dict):
37
- super().__init__(event_data)
38
- self.data = event_data.get("data", "")
42
+ class Config(IntegrationTrigger.Config):
43
+ provider = VellumIntegrationProviderType.COMPOSIO
44
+ integration_name = "test"
45
+ slug = "test"
46
+
47
+ def __init__(self, **kwargs: Any):
48
+ super().__init__(**kwargs)
49
+ self.data = kwargs.get("data", "")
39
50
 
40
51
  # WHEN we create a trigger instance
41
- result = TestTrigger({"data": "test"})
52
+ result = TestTrigger(data="test")
42
53
 
43
54
  # THEN it returns the expected trigger instance with populated attributes
44
55
  assert result.data == "test"
@@ -50,9 +61,14 @@ def test_integration_trigger__attribute_reference():
50
61
  class TestTrigger(IntegrationTrigger):
51
62
  value: str
52
63
 
53
- def __init__(self, event_data: dict):
54
- super().__init__(event_data)
55
- self.value = event_data.get("value", "")
64
+ class Config(IntegrationTrigger.Config):
65
+ provider = VellumIntegrationProviderType.COMPOSIO
66
+ integration_name = "test"
67
+ slug = "test"
68
+
69
+ def __init__(self, **kwargs: Any):
70
+ super().__init__(**kwargs)
71
+ self.value = kwargs.get("value", "")
56
72
 
57
73
  reference = TestTrigger.value
58
74
  assert isinstance(reference, TriggerAttributeReference)
@@ -61,7 +77,7 @@ def test_integration_trigger__attribute_reference():
61
77
  assert reference == TestTrigger.attribute_references()["value"]
62
78
 
63
79
  state = BaseState()
64
- trigger = TestTrigger({"value": "data"})
80
+ trigger = TestTrigger(value="data")
65
81
  trigger.bind_to_state(state)
66
82
  assert reference.resolve(state) == "data"
67
83
 
@@ -73,9 +89,14 @@ def test_integration_trigger__graph_syntax():
73
89
  class TestTrigger(IntegrationTrigger):
74
90
  value: str
75
91
 
76
- def __init__(self, event_data: dict):
77
- super().__init__(event_data)
78
- self.value = event_data.get("value", "")
92
+ class Config(IntegrationTrigger.Config):
93
+ provider = VellumIntegrationProviderType.COMPOSIO
94
+ integration_name = "test"
95
+ slug = "test"
96
+
97
+ def __init__(self, **kwargs: Any):
98
+ super().__init__(**kwargs)
99
+ self.value = kwargs.get("value", "")
79
100
 
80
101
  class TestNode(BaseNode):
81
102
  pass
@@ -97,9 +118,14 @@ def test_integration_trigger__multiple_entrypoints():
97
118
  class TestTrigger(IntegrationTrigger):
98
119
  msg: str
99
120
 
100
- def __init__(self, event_data: dict):
101
- super().__init__(event_data)
102
- self.msg = event_data.get("msg", "")
121
+ class Config(IntegrationTrigger.Config):
122
+ provider = VellumIntegrationProviderType.COMPOSIO
123
+ integration_name = "test"
124
+ slug = "test"
125
+
126
+ def __init__(self, **kwargs: Any):
127
+ super().__init__(**kwargs)
128
+ self.msg = kwargs.get("msg", "")
103
129
 
104
130
  class NodeA(BaseNode):
105
131
  pass
@@ -118,9 +144,12 @@ def test_integration_trigger__multiple_entrypoints():
118
144
 
119
145
 
120
146
  def test_integration_trigger__config_attribute():
121
- """IntegrationTrigger has optional config attribute."""
147
+ """IntegrationTrigger requires Config class with provider, integration_name, and slug."""
122
148
 
123
149
  # GIVEN IntegrationTrigger
124
- # THEN it has a config class variable
125
- assert hasattr(IntegrationTrigger, "config")
126
- assert IntegrationTrigger.config is None
150
+ # THEN it has a Config class with type annotations for required fields
151
+ assert hasattr(IntegrationTrigger, "Config")
152
+ assert hasattr(IntegrationTrigger.Config, "__annotations__")
153
+ assert "provider" in IntegrationTrigger.Config.__annotations__
154
+ assert "integration_name" in IntegrationTrigger.Config.__annotations__
155
+ assert "slug" in IntegrationTrigger.Config.__annotations__
@@ -43,20 +43,6 @@ def uuid4_from_hash(input_str: str) -> UUID:
43
43
  return UUID(bytes=bytes(hash_list))
44
44
 
45
45
 
46
- def get_trigger_id(trigger_class: "type[BaseTrigger]") -> UUID:
47
- """
48
- Generate a deterministic trigger ID from a trigger class using
49
- the class's module name and __qualname__ to ensure stability and uniqueness.
50
-
51
- Args:
52
- trigger_class: The trigger class to generate an ID for
53
-
54
- Returns:
55
- A deterministic UUID based on the trigger class module and qualname
56
- """
57
- return uuid4_from_hash(f"{trigger_class.__module__}.{trigger_class.__qualname__}")
58
-
59
-
60
46
  def get_trigger_attribute_id(trigger_class: "type[BaseTrigger]", attribute_name: str) -> UUID:
61
47
  """
62
48
  Generate a deterministic trigger attribute ID from a trigger class and attribute name
@@ -69,5 +55,5 @@ def get_trigger_attribute_id(trigger_class: "type[BaseTrigger]", attribute_name:
69
55
  Returns:
70
56
  A deterministic UUID based on the trigger class module, qualname, and attribute name
71
57
  """
72
- trigger_id = get_trigger_id(trigger_class)
58
+ trigger_id = trigger_class.__id__
73
59
  return uuid4_from_hash(f"{trigger_id}|{attribute_name}")
@@ -714,6 +714,50 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
714
714
 
715
715
  return state_class(**state)
716
716
 
717
+ @classmethod
718
+ def deserialize_trigger(cls, trigger_id: Optional[UUID], inputs: dict) -> Union[InputsType, BaseTrigger]:
719
+ """
720
+ Deserialize a trigger from a trigger_id and inputs dict.
721
+
722
+ If trigger_id is None, returns an instance of the workflow's Inputs class.
723
+ Otherwise, finds a trigger class that matches the trigger_id and creates an instance of that.
724
+
725
+ Parameters
726
+ ----------
727
+ trigger_id: Optional[UUID]
728
+ The UUID of the trigger class to instantiate. If None, returns workflow Inputs.
729
+
730
+ inputs: dict
731
+ The inputs to pass to the trigger or Inputs constructor.
732
+
733
+ Returns
734
+ -------
735
+ Union[InputsType, BaseTrigger]
736
+ Either an instance of the workflow's Inputs class (if trigger_id is None)
737
+ or an instance of the matching trigger class.
738
+
739
+ Raises
740
+ ------
741
+ WorkflowInitializationException
742
+ If trigger_id is provided but no matching trigger class is found in the workflow.
743
+ """
744
+ if trigger_id is None:
745
+ inputs_class = cls.get_inputs_class()
746
+ return inputs_class(**inputs)
747
+
748
+ trigger_classes = []
749
+ for subgraph in cls.get_subgraphs():
750
+ for trigger_class in subgraph.triggers:
751
+ if trigger_class.__id__ == trigger_id:
752
+ return trigger_class(**inputs)
753
+
754
+ trigger_classes.append(trigger_class)
755
+
756
+ raise WorkflowInitializationException(
757
+ message=f"No trigger class found with id {trigger_id} in workflow {cls.__name__}. "
758
+ f"Available trigger classes: {[trigger_class.__name__ for trigger_class in trigger_classes]}"
759
+ )
760
+
717
761
  @staticmethod
718
762
  def load_from_module(module_path: str) -> Type["BaseWorkflow"]:
719
763
  workflow_path = f"{module_path}.workflow"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 1.8.5
3
+ Version: 1.9.0
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0