You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: agent-framework/tutorials/workflows/simple-sequential-workflow.md
+28-10Lines changed: 28 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -203,7 +203,9 @@ In this tutorial, you'll create a workflow with two executors:
203
203
204
204
The workflow demonstrates core concepts like:
205
205
206
-
- Using the `@executor` decorator to create workflow nodes
206
+
- Two ways to define a unit of work (an executor node):
207
+
1. A custom class that subclasses `Executor` with an async method marked by `@handler`
208
+
2. A standalone async function decorated with `@executor`
207
209
- Connecting executors with `WorkflowBuilder`
208
210
- Passing data between steps with `ctx.send_message()`
209
211
- Yielding final output with `ctx.yield_output()`
@@ -260,13 +262,16 @@ class UpperCase(Executor):
260
262
261
263
**Key Points:**
262
264
263
-
- The `@executor` decorator registers this function as a workflow node
264
-
-`WorkflowContext[str]` indicates this executor sends a string downstream by specifying the first type parameter
265
-
-`ctx.send_message()` passes data to the next step
265
+
- Subclassing `Executor` lets you define a named node with lifecycle hooks if needed
266
+
- The `@handler` decorator marks the async method that does the work
267
+
- The handler signature follows a contract:
268
+
- First parameter is the typed input to this node (here: `text: str`)
269
+
- Second parameter is a `WorkflowContext[T_Out]`, where `T_Out` is the type of data this node will emit via `ctx.send_message()` (here: `str`)
270
+
- Within a handler you typically compute a result and forward it to downstream nodes using `ctx.send_message(result)`
266
271
267
272
### Step 3: Create the Second Executor
268
273
269
-
Create an executor that reverses the text and yields the final output from a method decorated with `@executor`:
274
+
For simple steps you can skip subclassing and define an async function with the same signature pattern (typed input + `WorkflowContext`) and decorate it with `@executor`. This creates a fully functional node that can be wired into a flow:
-`WorkflowContext[Never, str]` indicates this is a terminal executor that does not send any messages by specifying `Never` as the first type parameter but produce workflow outputs by specifying `str` as the second parameter
284
-
-`ctx.yield_output()` provides the final workflow result
285
-
- The workflow completes when it becomes idle
288
+
- The `@executor` decorator transforms a standalone async function into a workflow node
289
+
- The `WorkflowContext` is parameterized with two types:
290
+
-`T_Out = Never`: this node does not send messages to downstream nodes
291
+
-`T_W_Out = str`: this node yields workflow output of type `str`
292
+
- Terminal nodes yield outputs using `ctx.yield_output()` to provide workflow results
293
+
- The workflow completes when it becomes idle (no more work to do)
286
294
287
295
### Step 4: Build the Workflow
288
296
@@ -336,12 +344,22 @@ Workflow completed with result: DLROW OLLEH
336
344
337
345
## Key Concepts Explained
338
346
347
+
### Two Ways to Define Executors
348
+
349
+
1.**Custom class (subclassing `Executor`)**: Best when you need lifecycle hooks or complex state. Define an async method with the `@handler` decorator.
350
+
2.**Function-based (`@executor` decorator)**: Best for simple steps. Define a standalone async function with the same signature pattern.
351
+
352
+
Both approaches use the same handler signature:
353
+
- First parameter: the typed input to this node
354
+
- Second parameter: a `WorkflowContext[T_Out, T_W_Out]`
355
+
339
356
### Workflow Context Types
340
357
341
358
The `WorkflowContext` generic type defines what data flows between executors:
342
359
343
-
-`WorkflowContext[str]` - Sends a string to the next executor
344
-
-`WorkflowContext[Never, str]` - Terminal executor that yields workflow output of type string
360
+
-`WorkflowContext[T_Out]` - Used for nodes that send messages of type `T_Out` to downstream nodes via `ctx.send_message()`
361
+
-`WorkflowContext[T_Out, T_W_Out]` - Used for nodes that also yield workflow output of type `T_W_Out` via `ctx.yield_output()`
362
+
-`WorkflowContext` without type parameters is equivalent to `WorkflowContext[Never, Never]`, meaning this node neither sends messages to downstream nodes nor yields workflow output
Copy file name to clipboardExpand all lines: agent-framework/user-guide/workflows/core-concepts/workflows.md
+28-2Lines changed: 28 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -126,11 +126,17 @@ The framework performs comprehensive validation when building workflows:
126
126
127
127
### Execution Model
128
128
129
-
The framework uses a modified [Pregel](https://kowshik.github.io/JPregel/pregel_paper.pdf) execution model with clear data flow semantics and superstep-based processing.
129
+
The framework uses a modified [Pregel](https://kowshik.github.io/JPregel/pregel_paper.pdf) execution model, a Bulk Synchronous Parallel (BSP) approach with clear data flow semantics and superstep-based processing.
130
130
131
131
### Pregel-Style Supersteps
132
132
133
-
Workflow execution is organized into discrete supersteps, where each superstep processes all available messages in parallel:
133
+
Workflow execution is organized into discrete supersteps. A superstep is an atomic unit of execution where:
134
+
135
+
1. All pending messages from the previous superstep are collected
136
+
2. Messages are routed to their target executors based on edge definitions
137
+
3. All target executors run concurrently within the superstep
138
+
4. The superstep waits for all executors to complete before advancing to the next superstep
139
+
5. Any new messages emitted by executors are queued for the next superstep
The most important characteristic of the Pregel model is the synchronization barrier between supersteps. Within a single superstep, all triggered executors run in parallel, but the workflow will not advance to the next superstep until every executor in the current superstep completes.
159
+
160
+
This has important implications for fan-out patterns: if you fan out to multiple paths and one path contains a chain of executors while another is a single long-running executor, the chained path cannot advance to its next step until the long-running executor completes. All executors triggered in the same superstep must finish before any downstream executors can begin.
161
+
162
+
### Why Superstep Synchronization?
163
+
164
+
The BSP model provides important guarantees:
165
+
166
+
-**Deterministic execution**: Given the same input, the workflow always executes in the same order
167
+
-**Reliable checkpointing**: State can be saved at superstep boundaries for fault tolerance
168
+
-**Simpler reasoning**: No race conditions between supersteps; each superstep sees a consistent view of messages
169
+
170
+
### Working with the Superstep Model
171
+
172
+
If you need truly independent parallel paths that don't block each other, consider consolidating sequential steps into a single executor. Instead of chaining multiple executors (e.g., `step1 -> step2 -> step3`), combine that logic into one executor that performs all steps internally. This way, both parallel paths execute within a single superstep and complete in the time of the slowest path.
173
+
149
174
### Key Execution Characteristics
150
175
151
176
-**Superstep Isolation**: All executors in a superstep run concurrently without interfering with each other
177
+
-**Synchronization Barrier**: The workflow waits for all executors in a superstep to complete before advancing
152
178
-**Message Delivery**: Messages are delivered in parallel to all matching edges
153
179
-**Event Streaming**: Events are emitted in real-time as executors complete processing
154
180
-**Type Safety**: Runtime type validation ensures messages are routed to compatible handlers
0 commit comments