Sessions & Dialogue¶
Use SessionStep when a workflow needs a real conversation.
Unlike AgentStep, a session does not run to completion in one execution. It handles one user turn, suspends, waits for the next user message, and resumes later.
StepType: "session"
| Use case | Step |
|---|---|
| Autonomous tool-using work | AgentStep |
| Human↔AI multi-turn dialogue | SessionStep |
What a session is¶
A session turns one node in your workflow into a persistent dialogue boundary.
That means the workflow can:
- enter a conversation
- pause between user turns
- keep history across pauses
- exit when the conversation is complete
- continue to the next nodes in the graph
flowchart LR
A[classify] --> B[session: chat]
B --> C[summarize]
B -. user turn 1 .-> B
B -. user turn 2 .-> B
B -. user turn 3 / exit .-> C
The nodes before and after the session are normal workflow steps.
The session node is where the conversation lives.
Why use SessionStep¶
Dialogue inside a workflow¶
A workflow can mix pipelines and conversations.
For example:
- classify a request
- gather information through dialogue
- process the result
- confirm with the user
- continue the workflow
This lets you build flows like onboarding, support, approval, and guided intake without separating "chat" from "orchestration".
Efficient waiting¶
When a session is waiting for the next user message, it does not keep compute resources busy.
Instead, Spectra:
- checkpoints the workflow state
- stores the conversation history
- resumes when the next message arrives
This makes long-lived conversations practical.
Full agent loop per turn¶
Each user turn can still use tools internally.
So a single session turn can:
- call an LLM
- invoke tools
- observe results
- produce a final response to the user
The user sees one response, even if the system performed several tool calls behind the scenes.
Basic usage¶
services.AddSpectra(builder =>
{
builder.AddProvider<OpenAiCompatibleProvider>("openai", new OpenAiConfig
{
ApiKey = "sk-...",
DefaultModel = "gpt-4o"
});
builder.AddAgent("support", agent => agent
.WithProvider("openai")
.WithSystemPrompt("You are a helpful customer support agent.")
.WithTools("lookup_order", "check_inventory", "create_ticket"));
});
var workflow = Spectra.Workflow("support-chat")
.AddSessionStep("chat", agent: "support", options: new
{
greetingPrompt = "Hello! How can I help you today?",
maxTurns = 30,
exitPolicies = SessionExitPolicy.LlmDecides | SessionExitPolicy.UserCommand
})
.Build();
This is the common pattern:
- register an agent
- add a session step
- configure greeting, turn limit, and exit rules
How a session runs¶
A session has three main phases.
1. First entry¶
When the workflow reaches the session for the first time, it can generate a greeting and then suspend waiting for user input.
2. Each user turn¶
For every new user message, the session:
- appends the message to history
- runs the internal agent loop for that turn
- appends the assistant response
- checks exit conditions
- either suspends again or finishes
3. Exit¶
When an exit policy triggers, the session returns success with outputs like:
- full conversation history
- turn count
- exit reason
Then the workflow continues through its outgoing edges.
Exit policies¶
Exit policies control when the conversation ends.
You can combine multiple policies, and the first one that triggers ends the session.
| Policy | Value | How It Works |
|---|---|---|
LlmDecides |
1 |
The LLM calls an auto-injected end_session tool |
UserCommand |
2 |
The user types a command like /done, /exit, or /quit |
Condition |
4 |
A workflow state condition becomes true |
MaxTurns |
8 |
The session reaches maxTurns |
TokenBudget |
16 |
The cumulative token budget is reached |
Timeout |
32 |
The session exceeds its configured lifetime |
External |
64 |
An external API call ends the session |
Example:
var policies = SessionExitPolicy.LlmDecides
| SessionExitPolicy.UserCommand
| SessionExitPolicy.MaxTurns
| SessionExitPolicy.Timeout;
A practical default is:
- let the LLM end naturally
- allow the user to exit explicitly
- keep a hard turn limit as a safety net
end_session¶
When LlmDecides is enabled, Spectra injects an end_session tool for the model.
The tool is intercepted internally. It does not go through the normal tool registry.
History management¶
Long conversations need history control.
Spectra supports these strategies:
| Strategy | Behavior | When to Use |
|---|---|---|
Full |
Keep all messages | Short conversations |
SlidingWindow |
Keep only the last N messages | Longer conversations |
Summarize |
Summarize older messages | Not yet implemented |
Example:
.AddSessionStep("chat", agent: "support", options: new
{
historyStrategy = "SlidingWindow",
maxHistoryMessages = 40
})
History is persisted with the workflow state, so it survives checkpointing and resume.
Main inputs¶
All normal LLM inputs still apply, such as agent, provider, model, temperature, and maxTokens.
These inputs are specific to sessions:
| Input | Type | Default | Description |
|---|---|---|---|
userMessage |
string |
— | Current user message on resume |
tools |
List<string> |
— | Tool whitelist for the session |
maxIterations |
int |
10 |
Max tool-calling rounds per turn |
__greetingPrompt |
string |
— | Initial greeting template |
__exitPolicies |
int |
9 |
Combined SessionExitPolicy flags |
__maxTurns |
int |
50 |
Hard turn limit |
__tokenBudget |
int |
0 |
Total token budget across the session |
__timeout |
double |
0 |
Timeout in seconds from first entry |
__exitCondition |
string |
— | State key for condition-based exit |
__historyStrategy |
string |
"Full" |
Full, SlidingWindow, or Summarize |
__maxHistoryMessages |
int |
100 |
Window size for sliding history |
__exitCommands |
List<string> |
["/done", "/exit", "/quit"] |
Commands that trigger user exit |
Info
Inputs starting with __ configure session behavior. They are not sent to the LLM.
Outputs¶
When the session ends successfully, these outputs are available to downstream nodes:
| Output | Type | Description |
|---|---|---|
response |
string? |
Last assistant response |
messages |
List<LlmMessage> |
Full conversation history |
turnCount |
int |
Total completed turns |
totalInputTokens |
int |
Total prompt tokens across turns |
totalOutputTokens |
int |
Total completion tokens across turns |
exitReason |
string? |
Why the session ended |
These outputs make sessions composable with the rest of the graph.
For example, a later node can use:
to process the full conversation.
Events¶
Sessions emit events for monitoring and analytics.
| Event | When |
|---|---|
SessionTurnCompletedEvent |
After each turn |
SessionAwaitingInputEvent |
When the session suspends |
SessionCompletedEvent |
When the session ends |
Common patterns¶
Conversation → pipeline → conversation¶
A common design is:
- gather information through dialogue
- process it in the workflow
- return to the user for review or confirmation
var workflow = Spectra.Workflow("onboarding")
.AddSessionStep("interview", agent: "interviewer", options: new { ... })
.AddAgentStep("process", agent: "processor", inputs: new
{
userPrompt = "Process this application: {{nodes.interview.output.messages}}"
})
.AddSessionStep("review", agent: "reviewer", options: new
{
greetingPrompt = "Here's your processed application: {{nodes.process.output.response}}. Look good?"
})
.Edge("interview", "process")
.Edge("process", "review")
.Build();
Conditional exit routing¶
You can branch the workflow based on how the conversation ended.
var workflow = Spectra.Workflow("support")
.AddSessionStep("chat", agent: "support", options: new { ... })
.AddStep("escalate", new EscalateStep(), ...)
.AddStep("close", new CloseTicketStep(), ...)
.ConditionalEdge("chat", new()
{
["{{nodes.chat.output.exitReason}} == 'max_turns'"] = "escalate",
["default"] = "close"
})
.Build();
SessionStep vs AgentStep¶
AgentStep |
SessionStep |
|
|---|---|---|
| Interaction model | Autonomous | Interactive |
| Execution style | Runs to completion | Suspends between turns |
| Driver | The LLM | The human |
| Duration | Seconds to minutes | Minutes to days |
| State between calls | Single execution | Checkpointed and resumable |
| Best for | Task completion and processing | Chat, intake, support, onboarding |
| Tools | Used autonomously | Used inside each user turn |
| Exit | Model stops calling tools | Exit policies |
A simple mental model:
AgentStepis a workerSessionStepis a conversation