The Flow Tests feature generates and executes realistic, stateful API user journeys such as:
- login -> browse items -> open detail -> perform action
- create resource -> read back -> verify state
- transaction create -> transaction lookup
Unlike isolated single-endpoint tests, a flow is an ordered sequence where later steps can reuse values extracted from earlier responses (for example token, id, order_id).
This feature is available through:
- Backend API:
/api/flows/* - Frontend page:
/flows("Flow Tests" in nav)
Main modules:
- Parser enrichment:
backend/parser/openapi_parser.py - Flow generation:
backend/flows/generator.py - Flow execution:
backend/flows/runner.py - API routes:
backend/main.py - Persistence models:
backend/db/models.py - Pydantic contracts:
backend/models/schemas.py - Frontend page:
frontend/src/pages/FlowTests.tsx
Data lifecycle:
- Parse OpenAPI spec into enriched
ParsedAPI - Generate flow scenarios from API semantics
- Persist scenarios
- Run scenarios against target base URL with runtime context
- Persist run + step traces
- Display in Flow Tests UI history/detail views
Each parsed endpoint now contains more semantic hints used by flow generation:
securityrequires_authrequest_body_required_fieldsrequest_body_exampleresponse_examples- response
links(OpenAPI Links)
These are defined in ParsedEndpoint / ParsedResponse inside backend/models/schemas.py.
Core schema models in backend/models/schemas.py:
FlowScenarioFlowStepFlowExtractRuleFlowRunRecordFlowStepResultFlowGenerateRequestFlowRunRequest
Important behavior:
- Step ordering and duplicate
step_idare validated. FlowExtractRulesupportsfrom: body | headers | status_code.initial_contextdefaults to{}.
SQLite tables in backend/db/models.py:
flow_scenariosflow_runsflow_step_results
Persisted data includes full step-level trace payloads:
- resolved request
- response status/headers/body
- assertion counts
- extracted context delta
- error message
Entry point: generate_flows(...) in backend/flows/generator.py
If objectives are not explicitly provided, objectives are inferred from API structure:
- tags
- operationId
- summary/description keywords
- auth patterns
- resource/action patterns
Examples of inferred objectives:
- authentication and session workflow
- browse and discovery workflow
- detail retrieval workflow
- interaction workflow
- transactional lifecycle workflow
- create and verify workflow
Dependency hints come from:
- OpenAPI Links (highest signal)
- path params and common id/token patterns (
id,*Id,token,location) - producer-consumer variable relationships
These hints are converted to dependency edges and used to build valid step chains.
Before LLM refinement, the generator creates executable seed flows with:
- ordered steps
- extraction rules
- context variable reuse
- expected status/assertions defaults
This deterministic layer ensures there is always a runnable baseline.
When mode allows and API key is available, LLM refinement runs as:
- Scenario planner pass
- Step composer pass
- Critic/repair pass
If any stage fails or outputs invalid structures, system falls back safely to deterministic flows.
Before persistence, flows go through quality checks:
- unresolved path placeholders are rejected
- broken/dead variable chains are rejected
- step ordering/dependency coherence enforced
- mutating flows require read-after-write style verification
- mutation policy constraints enforced (
safe | balanced | full_lifecycle)
Summary metadata records:
- source (
llm_refinedordeterministic_fallback) - fallback reason
- objectives used
- dependency hint counts
- generation mode and mutation policy
Entry point: run_flow_scenario(...) in backend/flows/runner.py
Each run starts with:
ctx.run_idctx.timestamp- merged
initial_contextfrom request
Template syntax is supported in endpoint/path/query/header/body:
{{ctx.some_key}}- nested keys supported, for example
{{ctx.auth.token}}
For each step:
- Resolve templates from current context
- Execute HTTP request
- Validate
expected_statusand custom assertions - Run extraction rules (
body,headers,status_code) - Merge extracted values into context (only if step passes)
- Save step result trace
- If a required step fails (
required: true), execution stops immediately. - If a non-required step fails (
required: false), flow continues. - Final flow status becomes
passed,failed, orerror.
Routes in backend/main.py:
POST /api/flows/generateGET /api/flowsGET /api/flows/{flow_id}PUT /api/flows/{flow_id}POST /api/flows/runGET /api/flows/runsGET /api/flows/runs/{run_id}
Important request fields:
- Generation:
max_flowsmax_steps_per_flowinclude_negativegeneration_mode(hybrid_auto | llm_first | deterministic_first)mutation_policy(safe | balanced | full_lifecycle)personasapp_context
- Run:
flow_ids(optional; if omitted, latest batch is used)target_base_url(optional)initial_context(JSON object)
Implemented in frontend/src/pages/FlowTests.tsx.
The page has 4 sections:
- Generate Flows
- Latest Flow Batch (list + selection + detail)
- Run Flows
- Flow Run History + Run Detail
Behavior highlights:
- Invalid JSON in
app_contextorinitial_contextblocks submit. - Backend errors are shown with
detailwhen present. - Run trace JSON blocks are collapsed by default for large payloads.
- You can run either selected flows or latest batch fallback.
- Start backend and frontend.
- Parse an OpenAPI spec (Dashboard parse, or parse API route).
- Open
Flow Testspage. - Click
Generate Flows(defaults are enough for first run). - Verify generated list appears in Latest Flow Batch.
- In Run panel:
- set
target_base_url - keep
initial_contextas{}or add credentials/tokens if needed
- set
- Select flows and click
Run Selected(or clickRun Latest Batch). - Verify run-group summary.
- Open latest entry in Flow Run History.
- Inspect step-level traces:
- status/method/endpoint
- response code
- resolved request
- response body
- extracted context delta
Backend automated tests:
backend/tests/test_flow_generator.pybackend/tests/test_flow_runner.pybackend/tests/test_flow_routes.py
Covered areas include:
- objective inference
- dependency hints (including OpenAPI Links)
- LLM fallback behavior
- quality gates
- template resolution
- extraction from body/headers/status
- fail-fast required-step behavior
- route contracts for generate/run/history/detail
Frontend validation used in this phase:
npm run lintnpm run build- manual QA on
/flowspage
- Protocol scope is HTTP flows.
- No dedicated flow edit UI yet (backend
PUT /api/flows/{flow_id}exists). - Real execution of auth-protected APIs may require
initial_contextvalues. - Public demo APIs may be unstable or return noisy datasets.