flowstate

A declarative Finite State Machine engine for multi-turn conversational AI that uses YAML to define states, typed slots, and per-state model selection.

https://github.com/davidbmar/flowstate  ·  public  ·  shipped

What it is

flowstate is a Python library that structures complex conversations as deterministic state machines. Instead of relying on long chat histories and fragile system prompts, it breaks conversations into discrete states with specific goals and typed data contracts (slots). Each state can use a different LLM optimized for its specific task, ensuring context isolation, debuggability, and reliable data extraction.

Features

Quickstart

pip install flowstate
python scripts/demo_real_pizza.py

Architecture

flowchart TD
    User[User Input] --> Engine[flowstate Engine]
    Engine --> Context[FlowContext]
    Context --> Router[ModelRouter]
    Router --> Adapter[Model Adapter]
    Adapter --> LLM[External LLM]
    LLM --> Adapter
    Adapter --> Engine
    Engine --> Tools[Tool Registry]
    Tools --> External[External Systems]
    External --> Tools
    Engine --> NextState[Next State Decision]

How it's built

The core is a Python engine that loads YAML flow definitions. It uses a `ModelRouter` to dispatch requests to specific `ModelAdapter` implementations (Anthropic, Gemini, MLX, or Fake). The engine maintains a `FlowContext` tracking the current state and filled slots, executing a `step()` function that calls the adapter, parses structured JSON responses, updates slots, and evaluates transition conditions to move to the next state.

How it runs

sequenceDiagram
    participant App as Application
    participant Eng as flowstate Engine
    participant Ctx as FlowContext
    participant Rtr as ModelRouter
    participant Adp as ModelAdapter
    participant LLM as LLM Provider

    App->>Eng: step(input, ctx)
    Eng->>Ctx: get_current_state()
    Ctx-->>Eng: state_config
    Eng->>Rtr: get_adapter(state.model)
    Rtr-->>Eng: adapter_instance
    Eng->>Adp: complete(prompt, slots)
    Adp->>LLM: generate_response()
    LLM-->>Adp: raw_text/json
    Adp-->>Eng: AdapterResponse(slots, tool_calls)
    Eng->>Eng: update_slots(ctx)
    Eng->>Eng: evaluate_transitions()
    Eng-->>App: StepResult(next_state, updated_ctx)

How to apply & reuse

Define your conversation logic in a YAML file specifying states, goals, required slots, and transitions. Instantiate a `FlowContext` and load the flow using `load_flow()`. Use the `step()` function in your application loop, passing user input and the current context. Integrate specific LLM adapters via the `ModelRouter` to handle actual generation.

At a glance

CapabilitiesMulti-turn conversation managementStructured data extractionDynamic model routingState-based goal enforcementTool integrationConversation debugging
ComponentsYAML LoaderFlow ValidatorState EngineModel RouterModel AdaptersTool RegistryFlow Context
TechPythonYAMLJSONAnthropic SDKGoogle Generative AI SDKMLX
Depends onpyyamlanthropicgoogle-generativeaimlx-lm
Integrates withAnthropic ClaudeGoogle GeminiLocal MLX ModelsCustom Tool APIs
PatternsFinite State MachineAdapter PatternStrategy PatternDependency InjectionDeclarative Configuration
Reuse tagsconversational-aifsmllm-orchestrationstructured-outputyaml-config

Repo hygiene

✓ all on main — nothing unmerged.