v0.1
GitHub
RecTurnframeDeterministic conversational workflows for RustMini · flash · any providerv0.1 · MIT or Apache-2.0

Models propose.Code decides.Events confirm.

Turnframe is a Rust library for LLM conversational workflows that write to real records. Small checked tasks, sized for mini and flash models, read what a message means and stream each step as it is decided. Deterministic reducers decide what happens. The reply claims only what the ledger confirmed. Randomness lives in the reading, never in the effects.

cargo add turnframe
No RNG where it matters
Side effectsnever the wrong record, a stale revision or twiceBy construction
Claimsa receipt only for a committed eventBy construction
Workflow stateone phase, projected purelyBy construction
Understandingon a mini model; a misreading still meets every checkRNG · fails safe
Live corpus228 of 228 samples · gpt-5.4-mini at medium100.0%
RecFig. 1 · four turns of the travel desk, streamed frame by frame
ReplayF000
Turn 01 ·Trip 1 · outbound cancelled
Idle
effort
steps
tone
overlayfault
What your user sees
Inspector · for developers0/20
  1. Received
  2. Interpreted
  3. Reduced
  4. Executing
  5. Committed
  6. Composed
  7. Delivered
segment
coverage
route
locate
extract
verify
reduce
commit
compose
Waiting for a message.
Ledger · confirmed framesno confirm, no claim
No committed events. Nothing may be claimed.
F000/020
View
Scripted replay · effort buys judgment, never authority: at any level, a misread message cannot run a command its policy forbids.
Runs onOpenAIAzure OpenAIAnthropicGeminiVertex AIBedrockOllama· the examples need no key
Let the model understand language. Let your code control reality.
Models propose meaning.Small tasks, one narrow question each, answers checked by code. Mini and flash models are enough.
Reducers decide effects.Typed commands with an expected revision and an idempotency key, under policy.
Events decide claims.The reply says only what the ledger confirmed. No confirm, no claim.
01The Flow Map

Five steps, one direction.

Turnframe is built around the Flow Map: every turn runs the same five steps, and each hands the next only what it may decide. A model’s reading reaches a record only through a reducer, a policy and, for anything consequential, a card the user clicks.

  1. Projector · purePersisted state determines the viewThe stored record becomes one phase, its open obligations and at most one blocking card. The transcript is history, never state.
  2. Model · checkedSmall tasks propose what a message meansNarrow questions, each with a strict schema and a check in code, read the message into proposed acts that point at the user’s words.
  3. Code · deterministicReducers decide effectsThe whole turn is reduced at once into typed commands, each with an expected revision and an idempotency key, under policy.
  4. User · a clickInteractions authorize consequencesA consequential command waits on a card bound to the exact revision. A click on a card drawn before the record changed is refused.
  5. Ledger · eventsCommitted events decide claimsThe reply says only what the ledger recorded, so a failed or pending write is never described as done.

The Flow Map, step by step

02Frame data

Nine small questions, not one large prompt.

A message goes through a fixed chain of narrow tasks, each with a strict schema and a check in code. Dates and amounts are computed by code from what the model points at. No task needs more than a few hundred tokens, so a small, cheap model can run a real workflow.

Models propose

Proposed
01segmentWhich units the message holds: requests, questions, values, corrections, chitchat.
02coverageWhether a request or a question was missed.
03routeWhich offered operation each request asks for, one act each.
04locateWhich record it is about, when more than one could be.
05extractEach value, pointed at in the user’s own words.
06verifyWhether the act matches what the user said.

Code decides

07reduceWhich typed commands the whole turn compiles to, under policy.

Events confirm

Committed
08commitWhat the ledger records, at an expected revision.
09composeWhat the reply may claim: only what committed events back.

The turn pipeline, step by step

03Reliability model

No RNG where it matters. Honest RNG where it can’t hurt.

Reliability is not one accuracy number. Side effects, claims and workflow state are correct by construction: a violation is a defect a test can find, never model variance. Understanding is probabilistic, and it is only allowed to fail safe.

§PropertyEnforced byTarget
2.1Side-effect integrityNo write on the wrong case, over a newer revision, twice for one key, or from an ambiguous target.Reducer, command policy, ledger commit pathBy constructioneffectively 100%
2.2Claim integrityNo "created", "changed" or "sent" without the event or receipt that proves it. Unknown outcomes stay unknown.Ledger, receipt compositionBy constructioneffectively 100%
2.3Workflow-state consistencyOne lifecycle phase, projected purely from persisted state and the workflow version. The projector reads neither the clock nor the transcript.Pure projector, state explorationBy constructioneffectively 100%
2.4Semantic turn completionMini models read one narrow question at a time, so they are sometimes wrong. This is the only place RNG lives.Checked tasks, votes, mandatory safe degradationRNG · fails safe
2.5Conversational qualityTone varies with the model. The reply is reviewed before it is shown and cannot contradict a receipt.Reply tasks, offline judgesProduct-dependent
◌ When a reading misses, it can only recover into
A questionA missing value or an ambiguous record asks. The case is not touched.
An abstentionNo evidence, no command. The turn says so out loud.
A proposalRisky acts become a card. Nothing commits until the user answers.
A partial resultSafe acts apply, the rest are held, and every act gets a result.

The five properties and their release gates

04Low spec

Mini models. Frame‑perfect effects.

No task needs more than a few hundred tokens, so the reading runs on mini and flash models: on this release's corpus, gpt-5.4-mini passed 228 of 228 samples at medium. Accuracy is bought with checked calls on the same small model, and effects are identical at every setting. How each run was measured, and what the figures cannot show, is in the benchmarks.

Settings · effort preset
Reading · probabilistic · on a mini model
Live corpus passed100.0%228 of 228 samples
Model calls per item14.8an item is one turn, or a conversation of several
Cost per item$0.012$0.75 / $4.50 per M tokens
Turn latency, p507.7 s

The default. How a message is split and routed is read three times, and a verdict that finds fault is voted on again.

Effects · by construction · any model
Side effectsIdentical
Claims in the replyIdentical
Workflow stateIdentical
Cards, policy, revisionsIdentical

Code reads no level. A low turn that misreads a message still cannot run a command its policy forbids, claim what no event backs, or leave a record in a state its workflow cannot express.

Measured 28 and 29 September 2026 · gpt-5.4-mini at medium · ninth of 9 runs · 76-item live corpus, three samples each · docs/benchmarks.md

What is measured, and what is not claimed

05Matchup

Not an agent framework. The model never holds the controller.

Turnframe is for conversational applications that write to real records. The difference is where authority sits.

QuestionModel-calls-tools agentsTurnframe
Who performs a writeThe model calls a write toolA reducer compiles a typed command; policy decides
What the reply may claimWhatever the model writesOnly what a committed event or receipt backs
Two records matchUsually the most recent oneA selection card. Never a recency guess
A double click, a retry, a crashDepends on each toolOne idempotency key, one effect
A misread messageA wrong tool call, found laterChecked against the user’s words; a risky act still waits for its card
The model it needsLarge, with a long contextSmall: no task needs more than a few hundred tokens
06Controls

Plain Rust. No macros, no DSL.

  1. The projector turns the stored record into a view: one phase, its open obligations, at most one blocking card.
  2. Understanding splits the message, routes each request to an offered operation, and points at the value in the user’s own words.
  3. The reducer resolves the record and compiles a typed command with an expected revision and an idempotency key.
  4. The receipt is rendered from the committed event, never from a model’s prose. A timed-out call stays unknown until it is reconciled.
use std::sync::Arc; use turnframe::flow::WorkflowRegistry;use turnframe::runtime::config::OrchestratorConfig;use turnframe::runtime::orchestrator::Orchestrator; // 1. Your domains. Each is a pure projector plus an executor you write.let workflows = Arc::new(    WorkflowRegistry::builder()        .register(TripWorkflow::default(), Arc::clone(&trips))        .register(TravelerWorkflow::default(), Arc::clone(&travelers))        .build()?,); // 2. Models, persistence, and the records this user may address.//    The model never sees a record id: it sees a label.let orchestrator = Orchestrator::builder()    .workflows(workflows)    .providers(providers)    .stores(stores)    .case_directory(Arc::new(directory))    .config(OrchestratorConfig::conservative())    .build()?; // 3. One turn: "Register Marta Bianchi and put her on this trip"let answer = orchestrator.handle_turn(input).await?; // The reply says "added" only because a committed event backs it.assert!(answer.receipts().all(|receipt| receipt.is_event_backed()));
Abridged. TripWorkflow and TravelerWorkflow come from the test kit here and are yours in an application. The runnable version is the facade’s quickstart, a doc-test that needs no key, database or network.

The quickstart, in full

07Loadout

Install the facade. Pick features.

One dependency, the family behind feature flags. The core crate is pure types and the projector: it runs no async runtime and opens no connection.

PartCrateRoleFeature
Core
01turnframeFacade re-exporting the family behind feature flagsincluded
02turnframe-corePure types and the deterministic Flow Map projector; no async runtime, HTTP or databaseincluded
03turnframe-tasksSmall verified model tasks: repairs, in-place retries, votes, escalation, budgets, recordsincluded
04turnframe-understandThe understanding pipeline over those tasksincluded
05turnframe-runtimeTurn orchestration: reduction, interactions, commands, events, the reply, tracing, replayincluded
Providers
06turnframe-providerProvider-neutral model interfaces, capability routing, fallback policy, conformance suiteincluded
07turnframe-provider-openaiOpenAI, Azure OpenAI and OpenAI-compatible endpoints (profiles)openai
08turnframe-provider-anthropicAnthropic Messages APIanthropic
09turnframe-provider-geminiGoogle Gemini and Vertex AIgemini
10turnframe-provider-bedrockAWS Bedrock Conversebedrock
11turnframe-provider-ollamaOllamaollama
Persistence and prompts
12turnframe-storeObject-safe persistence traits and the deterministic in-memory storeincluded
13turnframe-store-postgresPostgreSQL reference store with migrations and expected-revision transactionspostgres
14turnframe-promptPrompt sources: prompts compiled in from your own repository, a bounded cache, an optional Langfuse v4 adapterprompts, langfuse
Proof
15turnframe-testTest kit: scripted providers and tasks, fake stores, sample workflows, workflow explorationtest-kit
16turnframe-evalEvaluation harness, scored per turn and per understanding taskeval
17turnframe-telemetryTracing spans, turnframe.* metrics, optional OpenTelemetry bridgetelemetry, otel
Alsoall-providersfull· turnframe-macros is reserved; no macros ship in 0.1
Press start

Run a turn. Frame by frame.

Read the architecture guide, then run the travel desk: four turns, four guarantees, and no key needed. When you want to see what a real model does with the contract, the console runs the same desk against whichever provider you have a key for. A mini one is enough.

    Type to search the guides, the decision records and the changelog.