11 Dynamic Selector#

Script: example/11_dynamic_selector.py.

OpenRath v1.2.1 adds flow.Selector, an LLM-backed routing decision over self-describing workflows. The selector returns a Workflow; your Python code decides whether and when to call it.

from rath import flow
from rath.session import Session

selector = flow.Selector(provider)
billing = flow.Agent(
    "Handle billing questions briefly.",
    provider,
    description="Billing, invoices, refunds, payment methods",
)
technical = flow.Agent(
    "Solve technical problems briefly.",
    provider,
    description="Installation, errors, configuration, troubleshooting",
)

session = Session.from_user_message("My invoice was charged twice.").to("local")
chosen = selector.forward(session, billing, technical)
if not isinstance(chosen, flow.EmptyWorkflow):
    session = chosen(session)

The same decision can drive a bounded loop:

rounds = 0
while not isinstance(
    chosen := selector.forward(session, technical, billing),
    flow.EmptyWorkflow,
):
    session = chosen(session)
    rounds += 1
    if rounds >= 4:
        break

API

v1.2.1 behavior

Workflow(description="...")

Stores the routing description. Agent and Compressor expose the same keyword.

Selector.forward(session, *workflows)

Returns one candidate Workflow or EmptyWorkflow; it does not return a Session.

EmptyWorkflow.forward(session)

Returns the same session unchanged.

select_session(...)

Returns (zero_based_index, description) or (-1, "") and does not create lineage.

OpenRath v1.2.2 adds the Session.text() accessor used by the shipped example:

print(session.text())  # latest non-empty assistant text, or None

Selector.__init__ still accepts on_event, but the v1.3.0 selection call does not forward that callback. Do not rely on streamed selector events in this version.

← Runnable Examples