Skip to main content

Journeys

Journeys enable multi-step conversational workflows with state tracking, branching, and backtracking. This page explains how the engine manages journey state and selects which step to execute.

The Journey Problem​

Guidelines Are Stateless​

A guideline such as "ask for their order number" has no inherent memory. It either matches the current context or does not. However, real conversations often follow multi-step flows:

  1. Greet and identify intent
  2. Collect required information
  3. Perform the action
  4. Confirm completion

Tracking position within such a flow presents a challenge. Encoding all the logic into guideline conditions quickly becomes unwieldy:

# This quickly becomes unmanageable
condition="Customer wants to return AND we haven't asked for order number yet"
condition="Customer wants to return AND we asked for order number AND they provided it AND we haven't initiated the return yet"

The Solution: Separate Journey Graphs​

Journeys provide a structured way to define multi-step flows. Instead of encoding state in guideline conditions, the developer defines:

  • Nodes: Steps with associated actions (guidelines)
  • Edges: Transitions between steps (optionally conditional)
  • Activation conditions: The circumstances under which this journey begins

The engine tracks the current node position and handles transitions automatically.

Journey Structure​

Components​

Entry Condition: A guideline whose condition activates the journey:

condition="Customer wants to book a taxi"

Nodes: Each node has an action (what the agent should do at this step):

node_1.action = "Ask for their pickup location"
node_2.action = "Ask for their dropoff location"

Edges: Define transitions between nodes. Edges can be:

  • Unconditional: The transition occurs automatically when the current node completes.
  • Conditional: The transition occurs only if a specified condition is met.

Root Node: The entry/exit point. Returning to root after visiting other nodes signals journey completion.

Node Guidelines​

Internally, each node's action becomes a guideline with a special ID format:

journey_node:{journey_id}:{node_id}

These "journey node guidelines" are evaluated by the Journey Node Selection batch, which reasons about the full journey state.

Journey State Algorithm​

The engine tracks journey progress in journey_paths:

STATE: journey_paths = {
journey_id: [node_id, node_id, ...]
}

The path is a list of visited nodes, representing the route taken through the journey.

State Transitions​

ALGORITHM: Journey State Update

ON guideline_match(guideline):

IF guideline is journey activation condition:
# New journey activated
journey = find_journey_for(guideline)
journey_paths[journey.id] = [journey.root_id]

IF guideline is journey node (journey_node:{jid}:{nid}):
journey_id, node_id = parse(guideline.id)
current_path = journey_paths[journey_id]

IF node_id IN current_path:
# BACKTRACKING: Customer changed context
# Truncate path to this node
index = current_path.index(node_id)
journey_paths[journey_id] = current_path[:index+1]

ELSE:
# FORWARD PROGRESS: Moving to new node
journey_paths[journey_id].append(node_id)

# Check for completion
IF node_id == journey.root_id AND len(current_path) > 1:
# Returned to root after visiting other nodes
# Journey is complete
DELETE journey_paths[journey_id]

Forward Progress​

In the normal flow, the customer provides information and the journey advances to the next node:

Path: [root] → [root, node_1] → [root, node_1, node_2] → [root, node_1, node_2, node_3]

Each new node is appended to the path as the journey progresses.

Backtracking​

Backtracking occurs when the customer changes their mind or provides conflicting information:

When the customer's new information invalidates previously collected data, the engine detects this and backtracks to the appropriate node.

Completion Detection​

A journey completes when the path returns to root after visiting other nodes:

Path: [root, n1, n2, n3, root]
↑ ↑
Started Completed

Upon completion, the journey is removed from journey_paths and its guidelines no longer match.

Journey Node Selection​

The Challenge​

When a journey is active, multiple nodes might appear relevant:

  • The current node (the present position in the journey)
  • The next node (the intended destination)
  • An earlier node (if backtracking is required)

Journey Node Selection is a specialized guideline matching batch that determines which node should execute.

Selection Algorithm​

ALGORITHM: Journey Node Selection

INPUT: active_journey, current_path, context
OUTPUT: selected_node or NO_MATCH

1. IDENTIFY candidate nodes:
- Current node in path
- Nodes reachable via edges from current node
- Previous nodes in path (for backtracking)

2. EVALUATE each candidate:
- Does the conversation justify this node?
- Is there new information invalidating later nodes?
- Are transition conditions met?

3. DETERMINE action:
IF conversation invalidates current progress:
- BACKTRACK to appropriate earlier node
ELSE IF transition condition to next node is met:
- PROGRESS to next node
ELSE:
- STAY at current node (or re-execute if needed)

4. RETURN selected_node with rationale

Backtracking Signals​

The selection batch identifies signals that require backtracking:

  • Contradictory information: "Actually, my pickup is somewhere else"
  • Explicit corrections: "No, I said Oak Avenue, not Main Street"
  • Context shifts: "Wait, it's not for me, it's for my son"

When such signals are detected, the system selects an earlier node and truncates the path accordingly.

Journey Pruning for Efficiency​

With many journeys defined, evaluating all their guidelines is expensive. Parlant uses prediction to focus evaluation:

Top-K Journey Prediction​

ALGORITHM: Journey Pruning

INPUT: all_journeys, context, active_journeys
OUTPUT: journeys_to_evaluate

1. IF active_journeys exist:
- ALWAYS include all active journey guidelines
- PREDICT Top-K other journeys that might activate
- Include their activation condition guidelines

2. IF no active_journeys:
- PREDICT Top-K journeys by semantic relevance to context
- Only evaluate guidelines for those journeys

3. ALWAYS include:
- Non-journey-scoped (global) guidelines

Two-Pass Matching​

In some cases, tool results activate a journey that was not initially predicted:

1. First Pass: Match with predicted Top-K journeys
2. Tool calls execute, return new information
3. Check: Did any unpredicted journey's condition now match?
4. Second Pass: If yes, evaluate that journey's node guidelines

This mechanism identifies journeys that become relevant due to runtime information.

Journey-Guideline Integration​

Scoping Guidelines to Journeys​

Guidelines can be scoped to only apply during certain journeys:

# This guideline only applies during the returns journey
guideline = await agent.create_guideline(
condition="Customer provides order number",
action="Look up the order and verify it's returnable",
tags=["returns_journey"]
)

When the returns journey is not active, this guideline is excluded from evaluation entirely.

Journey Tools​

Journey nodes can have associated tools:

node = JourneyNode(
action="Verify the order is returnable",
tools=["lookup_order", "check_return_eligibility"]
)

When this node is selected, its tools are considered for execution, following the same tool-enabled guideline flow as regular guidelines.

Why This Design?​

Why Separate Journeys from Guidelines?​

Mixing journey state into guideline conditions creates several problems:

  • A combinatorial explosion of conditions
  • Difficulty reasoning about the flow
  • No clear visualization of the process

Separating journeys from guidelines provides:

  • Clean guideline conditions that focus on "what" should happen
  • Explicit flow definitions that focus on "when" and "in what order"
  • Easier debugging by clearly identifying the current node position

Why Graph-Based?​

Trees are too restrictive because real conversations branch and merge. Full state machines introduce excessive complexity. Directed graphs provide an optimal balance:

  • Nodes represent steps in the workflow
  • Edges define allowed transitions between nodes
  • Conditions on edges enable branching logic
  • Backtracking is handled through path analysis

Tradeoffs​

ChoiceBenefitCost
Path trackingProvides precise position tracking within journeysRequires memory allocation per active journey
BacktrackingAccommodates natural conversation flowIntroduces complex selection logic
Top-K pruningEnables efficient evaluationMay miss unexpected journey activations
Two-pass matchingIdentifies runtime-activated journeysIntroduces additional latency

What's Next​