Streaming¶
Spectra can stream workflow events in real time while a workflow is running.
Instead of waiting for the full workflow to finish, you can consume events as they happen.
This is useful for:
- live UIs
- chat interfaces
- progress indicators
- server-sent event endpoints
- real-time token output
Stream a workflow¶
Use IWorkflowRunner.StreamAsync(...) to execute a workflow and consume events with await foreach.
await foreach (var evt in runner.StreamAsync(workflow, StreamMode.Tokens, initialState))
{
switch (evt)
{
case TokenStreamEvent token:
Console.Write(token.Token);
break;
case StepCompletedEvent step:
Console.WriteLine($"\n[{step.NodeId}] completed in {step.Duration}");
break;
case WorkflowCompletedEvent done:
Console.WriteLine($"\nWorkflow finished. Success: {done.Success}");
break;
}
}
There is also an overload that accepts RunContext:
await foreach (var evt in runner.StreamAsync(workflow, StreamMode.Tokens, state, runContext))
{
// ...
}
Stream modes¶
StreamMode controls how much of the event stream you receive.
| Mode | Includes | Best for |
|---|---|---|
Tokens |
Every event, including token deltas | Live LLM output |
Messages |
Every event except TokenStreamEvent |
Step-level progress without token noise |
Updates |
StepCompletedEvent, StateChangedEvent, WorkflowCompletedEvent, StepInterruptedEvent |
Progress views and dashboards |
Values |
StateChangedEvent, WorkflowCompletedEvent |
Reactive state consumers |
Custom |
Every event (same as Tokens) — filter downstream yourself |
Advanced consumers |
Use the narrowest mode that matches your UI or integration.
Token streaming¶
When you run a workflow with StreamAsync(...), Spectra enables token-level streaming for LLM steps that support it.
Each token chunk is emitted as a TokenStreamEvent.
| Field | Description |
|---|---|
Token |
The emitted text chunk |
TokenIndex |
Zero-based position of the chunk within the current node's stream (resets per node) |
IsComplete |
true on the final token for the current node's stream |
Which steps support token streaming¶
Token streaming is supported by:
PromptStepAgentStepSessionStep
For AgentStep and SessionStep, streaming fires on iterations where no tools are in the request. When tools are present (i.e. the agent is mid-loop calling tools), the LLM response must be fully parsed before tool calls can be dispatched, so those iterations are not streamed token-by-token. In practice, a tool-using agent streams its final natural-language response once it stops calling tools.
Streaming does not replace normal events¶
Streaming adds a live delivery path, but it does not replace your normal event sinks.
That means:
- your existing event sink can still write logs, audit records, or database events
StreamAsync(...)gives you a second live stream for the current consumer
This is important if you want both:
- persistent observability
- live UI updates
How it works¶
Internally, the runner writes workflow events into a streamable channel while still publishing them to the configured event sink.
You usually do not need to manage this directly.
The important behavior is:
- steps emit events as they run
- token-capable steps emit token events
- the runner yields those events through
IAsyncEnumerable<WorkflowEvent>
IEventStream¶
For advanced event consumption, Spectra also provides IEventStream.
public interface IEventStream
{
IAsyncEnumerable<TEvent> SubscribeAsync<TEvent>(
CancellationToken cancellationToken = default)
where TEvent : WorkflowEvent;
IAsyncEnumerable<WorkflowEvent> SubscribeAllAsync(
StreamMode mode = StreamMode.Updates,
CancellationToken cancellationToken = default);
}
Use this when you want:
- typed subscriptions
- event-specific consumers
- filtered access without manually switching over the whole event stream
Example:
SubscribeAsync<StepCompletedEvent>()for step completions onlySubscribeAllAsync(StreamMode.Values)for state and completion events only
A simple mental model¶
RunAsync(...)waits for the workflow resultStreamAsync(...)gives you the workflow result as a live event stream
That is the core distinction.