T
Telephony SOPKnowledge Base
Search
← All topics

Context Builder — Multi-Step Guided Flows in Python Agents SDK

runnable

Use ContextBuilder when an AI agent needs structured, step-by-step conversations. Up to 50 contexts per builder, 100 steps per context. Covers single-context steps, multi-context with cross-context transitions, system_prompt overrides, and create_simple_context.

signalwireagents-sdkcontext-buildermulti-stepguided-flow
Agent trigger phrases: ContextBuilder Python · multi-step AI agent flow · guided conversation SignalWire · add_step set_step_criteria · set_valid_contexts · create_simple_context

Context Builder — Multi-Step Guided Flows

Use ContextBuilder when an AI agent needs structured, step-by-step conversations rather than free-form prompting. Each context has its own system prompt and a chain of steps. Steps gate progression with criteria, allowed tools, and valid next-steps.

Limits: 50 contexts per builder, 100 steps per context.

Single context, sequential steps

from signalwire import AgentBase, FunctionResult

class OrderAgent(AgentBase):
    def __init__(self):
        super().__init__(name="order-agent")
        self.add_language("English", "en-US", "rime.spore")
        self.prompt_add_section("Role", "You help customers place orders.")

        contexts = self.define_contexts()
        order = contexts.add_context("default")

        order.add_step("get_item") \
            .set_text("Ask what item they want to order.") \
            .set_step_criteria("Customer has specified an item") \
            .set_valid_steps(["get_quantity"])

        order.add_step("get_quantity") \
            .set_text("Ask how many they want.") \
            .set_step_criteria("Customer has specified a quantity") \
            .set_valid_steps(["confirm"])

        order.add_step("confirm") \
            .set_text("Confirm order details and thank them.") \
            .set_step_criteria("Order confirmed") \
            .set_end(True)

The agent advances when step_criteria is satisfied. set_valid_steps([...]) limits which steps are reachable next; out-of-list jumps are blocked.

Multi-context flow with cross-context transitions

contexts = self.define_contexts()

# Triage / menu context
main = contexts.add_context("default")
main.add_step("menu") \
    .set_text("Ask whether they need sales, support, or billing.") \
    .set_functions("none") \
    .set_valid_contexts(["sales", "support", "billing"])

# Sales context
sales = contexts.add_context("sales")
sales.set_system_prompt("You are a friendly sales representative.")
sales.add_step("qualify") \
    .set_text("Understand what product the caller is interested in.") \
    .set_functions(["check_inventory", "get_pricing"]) \
    .set_valid_steps(["close"])
sales.add_step("close") \
    .set_text("Close the sale or schedule a follow-up.") \
    .set_valid_contexts(["default"])

# Support context
support = contexts.add_context("support")
support.set_system_prompt("You are a tier-2 support engineer.")
support.add_step("triage").set_text("Get problem details, system info, and urgency.")

# Billing context
billing = contexts.add_context("billing")
billing.set_system_prompt("You are a billing specialist. Verify account before answering.")
billing.add_step("verify").set_text("Ask for the last four digits of the account.")

Crossing contexts requires set_valid_contexts([...]) on the source step. The SDK blocks the transition otherwise.

Step configuration table

| Setter | Purpose | |---|---| | .set_text("...") | The step's prompt instruction (what the AI should do in this step). | | .set_step_criteria("...") | The exit condition. The AI evaluates whether this is met. | | .set_valid_steps([...]) | Whitelist of step names reachable from here. | | .set_valid_contexts([...]) | Whitelist of contexts reachable from here. | | .set_functions([...]) | SWAIG functions usable inside this step. "none" disables tools entirely. | | .set_end(True) | Mark this as the terminal step of the context. |

Context configuration

| Setter | Purpose | |---|---| | .set_system_prompt("...") | Override the agent's base prompt for this context. | | .add_step("name") | Add a new step. Returns the step builder for fluent chaining. |

create_simple_context — standalone, no builder

For one-off contexts without the full builder pattern:

from signalwire import create_simple_context

ctx = create_simple_context()  # name defaults to "default"
ctx.add_step("greet").set_text("Say hello to the caller.")
ctx.add_step("help").set_text("Ask how you can help today.")

Use this when you have a single context and don't need cross-context transitions.

Triggering transitions from SWAIG handlers

A SWAIG function can advance the flow programmatically:

from signalwire import FunctionResult

@agent.tool(description="Caller wants sales")
def route_to_sales(args, raw_data=None):
    return FunctionResult("Connecting you to sales.").swml_change_context("sales")

@agent.tool(description="Move to confirmation step")
def proceed_to_confirm(args, raw_data=None):
    return FunctionResult("Let me confirm your order.").swml_change_step("confirm")

.swml_change_step(name) jumps within the active context. .swml_change_context(name) jumps to a different context (must be allowed via set_valid_contexts).

Context vs free-form prompting — when to use which

| Pattern | Use this | |---|---| | Open-ended chat with optional tools | Free-form prompt (no ContextBuilder). | | 2-4 step ordered process (intake, quote, schedule) | Single context with sequential steps. | | Multi-persona handoff (triage → specialist) | Multi-context with set_valid_contexts. | | Stateful flow with strict gating | ContextBuilder with step_criteria and set_valid_steps. |

Anti-patterns

  • Defining 30+ steps in one context — split into multiple contexts.
  • Skipping set_valid_steps or set_valid_contexts — the AI may jump anywhere, defeating the structure.
  • Setting set_functions("none") in a step that needs tools — the AI will improvise instead of calling SWAIG.
  • Re-using step names across contexts — fine, but confuses logs. Prefix with context name (sales_qualify, support_qualify).
  • Manually editing prompt.text and a context's system_prompt to overlap — the context prompt wins inside that context.

See also