Skip to content

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Dec 10, 2025

Summary

Makes the ENTRYPOINT node optional in workflow serialization. When all graph branches originate from triggers (IntegrationTrigger/ScheduleTrigger), no ENTRYPOINT node is created. For triggerless workflows with partial WorkflowMetaDisplay overrides (e.g., only display_data set), the backfill logic in _generate_workflow_meta_display ensures proper entrypoint IDs are generated by merging overrides with defaults.

Also fixes duplicate edge IDs when multiple non-manual triggers target the same node - each trigger edge now gets a unique deterministic ID based on workflow_id|trigger_edge|trigger_id|target_node_id.

This is the Python SDK counterpart to the codegen changes in #3345.

Review & Testing Checklist for Human

  • Verify edge ID generation change doesn't break existing workflows (snapshot updated for simple_manual_trigger_workflow)
  • Verify multiple IntegrationTriggers targeting the same node produce unique edge IDs
  • Verify triggerless workflows with partial WorkflowMetaDisplay overrides (only display_data set) still create ENTRYPOINT nodes with valid IDs
  • Test end-to-end with codegen PR [APO-2321] Generate graphs without entrypoint node #3345 and run vellum push on workflows with triggers

Test Plan:

  1. Serialize a workflow with two IntegrationTriggers pointing to the same node - verify edges have unique IDs
  2. Serialize a triggerless workflow with WorkflowMetaDisplay(display_data=...) - verify ENTRYPOINT node exists
  3. Serialize an IntegrationTrigger-only workflow - verify NO ENTRYPOINT node, edges use trigger ID

Notes

  • Edge ID generation now uses deterministic hash for all trigger edges (not just when metadata mapping is missing)
  • New regression tests: test_partial_workflow_meta_display_override.py, test_two_integration_triggers_same_node_unique_edge_ids

@vellum-automation
Copy link
Contributor

@codex review

@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 50 to +54
@dataclass
class WorkflowMetaDisplay:
entrypoint_node_id: UUID
entrypoint_node_source_handle_id: UUID
entrypoint_node_display: NodeDisplayData = Field(default_factory=NodeDisplayData)
entrypoint_node_id: Optional[UUID] = None
entrypoint_node_source_handle_id: Optional[UUID] = None
entrypoint_node_display: Optional[NodeDisplayData] = None

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Backfill entrypoint defaults when overrides omit IDs

The entrypoint metadata on WorkflowMetaDisplay is now optional (lines 52‑54), but _generate_workflow_meta_display still copies user overrides verbatim while serialize() only builds an ENTRYPOINT node when both IDs are set (base_workflow_display.py:299‑305). For a triggerless workflow that overrides only the viewport, e.g. workflow_display = WorkflowMetaDisplay(display_data=…), the IDs default to None, the guard skips node creation, and the serialized workflow ends up missing the required ENTRYPOINT node. This newly breaks serialization for workflows without triggers whenever partial overrides are supplied.

Useful? React with 👍 / 👎.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks legit

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1765348829-optional-entrypoint-node branch from 530f9c0 to 6937d60 Compare December 11, 2025 00:12
Comment on lines 50 to +54
@dataclass
class WorkflowMetaDisplay:
entrypoint_node_id: UUID
entrypoint_node_source_handle_id: UUID
entrypoint_node_display: NodeDisplayData = Field(default_factory=NodeDisplayData)
entrypoint_node_id: Optional[UUID] = None
entrypoint_node_source_handle_id: Optional[UUID] = None
entrypoint_node_display: Optional[NodeDisplayData] = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks legit

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1765348829-optional-entrypoint-node branch from 2e3aa2f to 6d159a3 Compare December 15, 2025 15:24
@NgoHarrison NgoHarrison marked this pull request as ready for review December 15, 2025 15:51
@NgoHarrison
Copy link
Contributor

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

trigger_edge_dict: Dict[str, Json] = {
"id": str(stable_edge_id) if stable_edge_id else str(target_entrypoint_display.edge_display.id),
"source_node_id": str(source_node_id),
"source_handle_id": str(source_handle_id),
"target_node_id": str(target_node_display.node_id),

P2 Badge Duplicate IDs for multiple trigger edges without entrypoint node

When all branches are trigger-sourced the ENTRYPOINT node is skipped, but trigger edges still fall back to target_entrypoint_display.edge_display.id when no metadata mapping exists. That edge display ID is generated once per target node (using the workflow display’s entrypoint UUID), so multiple non-manual triggers feeding the same node will serialize distinct edges with identical id values (e.g., two IntegrationTriggers pointing at one process node). Clients typically treat edge IDs as unique keys, so these duplicates can collapse edges or hide triggers whenever metadata.json lacks explicit IDs.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@NgoHarrison
Copy link
Contributor

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@NgoHarrison NgoHarrison merged commit 4c09c35 into main Dec 15, 2025
9 checks passed
@NgoHarrison NgoHarrison deleted the devin/1765348829-optional-entrypoint-node branch December 15, 2025 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants