Skip to content

feat: implement node name validation and update workflow construction to return errors#797

Merged
hanorik merged 2 commits into
google:wolo/workflowsfrom
hanorik:name_validator
May 7, 2026
Merged

feat: implement node name validation and update workflow construction to return errors#797
hanorik merged 2 commits into
google:wolo/workflowsfrom
hanorik:name_validator

Conversation

@hanorik
Copy link
Copy Markdown
Contributor

@hanorik hanorik commented May 5, 2026

This PR introduces node name validation to ensure that different nodes in a workflow do not share the same name. It also updates workflow construction functions to return errors on validation failure.

Changes:

  • workflow/validator.go : Added validateUniqueNames to check that all nodes in the workflow have unique names, preventing accidental reuse or ambiguity.
  • workflow/workflow.go:
    • Updated Chain, Concat, and New to return an error.
    • Integrated validateUniqueNames into these construction functions.
  • workflow/workflow_test.go:
    • Updated existing tests to handle the new error returns from Chain and New.
    • Added TestUniqueNames to verify that duplicate node names are correctly identified and handled.

@hanorik hanorik requested review from anFatum and wolo-lab May 5, 2026 13:36
Copy link
Copy Markdown
Contributor

@anFatum anFatum left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread workflow/workflow.go Outdated
Comment thread workflow/validator.go Outdated
Comment thread workflow/workflow.go Outdated
Comment thread workflow/validator.go Outdated
Comment thread workflow/workflow_test.go Outdated
Comment thread workflow/workflow.go Outdated
Comment thread workflow/workflow_test.go Outdated
Comment thread workflow/validator.go Outdated
Comment thread workflow/workflow.go Outdated
Comment thread workflow/workflow.go Outdated
@hanorik hanorik requested a review from wolo-lab May 6, 2026 11:51
@hanorik hanorik merged commit 0b92728 into google:wolo/workflows May 7, 2026
1 check passed
wolo-lab added a commit that referenced this pull request May 8, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab pushed a commit that referenced this pull request May 11, 2026
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 11, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 12, 2026
…ecution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab added a commit that referenced this pull request May 13, 2026
…ion (#803)

* workflow: introduce scheduler-based engine with goroutine-per-node execution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab pushed a commit that referenced this pull request May 18, 2026
wolo-lab added a commit that referenced this pull request May 18, 2026
…ion (#803)

* workflow: introduce scheduler-based engine with goroutine-per-node execution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab pushed a commit that referenced this pull request May 25, 2026
wolo-lab added a commit that referenced this pull request May 25, 2026
…ion (#803)

* workflow: introduce scheduler-based engine with goroutine-per-node execution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
wolo-lab pushed a commit that referenced this pull request Jun 2, 2026
wolo-lab added a commit that referenced this pull request Jun 2, 2026
…ion (#803)

* workflow: introduce scheduler-based engine with goroutine-per-node execution

Squashes the workflow engine WIP work onto the latest wolo/workflows
base. The branch had 8 incremental commits; this single commit
captures the cumulative state on top of upstream PR #795 (EdgeBuilder),
PR #796 (NodeConfig), and PR #797 (node name validation).

Architecture:
  * Goroutine-per-node execution model: each scheduled node runs in
    its own goroutine, pushing events into a buffered channel.
  * Single consumer goroutine (runState.run) drains the channel,
    applies state-side effects, yields events to the caller, and
    schedules successors when nodes complete.
  * Replaces the legacy in-process BFS in Workflow.Run with the new
    scheduler, removing findNextNodes and the inline event loop.

New types and constructors:
  * BaseNode (and NewBaseNode) for shared Name/Description/Config
    bookkeeping; FunctionNode and toolNode now embed it.
  * Graph helpers in graph.go: indexed adjacency for O(1) successor
    lookup.
  * RunState (persistable) and runState (in-process scheduler bag)
    in state.go; node lifecycle map (NodeStatus + per-node accumulators).
  * NodeContext wraps InvocationContext with a per-node TriggeredBy
    accessor; agent.InvocationContext gains TriggeredBy() returning
    "" for non-workflow contexts (mocks updated accordingly).
  * Scheduler (scheduler.go): runNode goroutine wrapper, eventQueue,
    cancelAll, and the run consumer loop with sibling cancellation
    and per-node timeout.

Routing and validation:
  * findSuccessors honours unconditional edges, concrete Routes, and
    the Default fallback. Silent dead-ends remain intentional per
    adk-python parity.
  * Workflow.New now returns (*Workflow, error) — picks up the name
    validation introduced upstream by PR #797.

NodeConfig timeout shape:
  * Timeout is time.Duration (not *time.Duration), with zero meaning
    "inherit parent context". Matches net.Dialer.Timeout and the
    http.Server.*Timeout convention; keeps call sites free of pointer
    boilerplate.
  * Adds RerunOnResumeOr / WaitForOutputOr accessor helpers for
    pointer-typed pointer-typed tri-state fields.
  * Adds TestDefaultRetryConfig from upstream PR #796.

Examples and tests:
  * examples/workflow/basic uses NodeConfig{RetryConfig: DefaultRetryConfig()}
    to demo the helper.
  * 7 New(edges) callers updated for the new (*Workflow, error)
    signature.

Tests verified: go build ./..., go vet ./..., go test -race
./workflow/... ./agent/workflowagent/... all pass.
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