# OpenRath v1.2.1 Released May 30, 2026. ## What changed v1.2.1 adds dynamic workflow routing without introducing a graph engine or a workflow DSL. A `Selector` asks the configured model to choose among the candidate workflows' `description` values; ordinary Python still owns the branch or loop. | Addition | Contract | | --- | --- | | `flow.Selector` | Returns the chosen `Workflow`, never a `Session`. | | `flow.EmptyWorkflow` | Identity workflow used for no-match and completion. | | `Workflow.description` | Optional text used to describe a routing candidate. | | `session.select_session` | One-shot routing primitive returning an index and description. | | `example/11_dynamic_selector.py` | Demonstrates `if` and bounded `while` routing patterns. | ## Compatibility - Existing workflows remain compatible because `description` defaults to an empty string. - `Selector.forward(...)` intentionally differs from the base `Workflow.forward(session) -> Session` convention. - Selection disables tools and does not create a new session or lineage edge. - The v1.2.1 example called a missing `Session.text()` method. v1.2.2 adds the accessor and makes the example runnable without that workaround. Full code changes: [v1.2.0...v1.2.1](https://github.com/Rath-Team/OpenRath/compare/v1.2.0...v1.2.1).