This release is a pre-release and may not be stable for production use.
tuvl
/ˈtuːvəl/ · തൂവൽ · feather
Typed workflows of agents — code, database/HTTP/MCP tools, rules, models,
bounded tool loops and people — on a durable, journaled runtime,
built spec-first and served as REST, SSE and MCP.
tuvl 2.0 is a redesign with no 1.x compatibility layer — see the CHANGELOG. Versions follow SemVer.
A tuvl workflow is a graph of agents. Each agent has a typed contract — inputs, outputs, the
signals it emits — and an engine that implements it:
| Engine | Determinism | |
|---|---|---|
code |
a Python function | deterministic |
tool |
a database, HTTP or MCP operation | deterministic |
decide |
ordered rules, then an optional decision model | deterministic → bounded |
llm |
one structured model call | bounded |
loop |
a model using tools within hard budgets | bounded |
human |
a form for a person | external |
pending |
a contract waiting for an implementation | — |
Signals route to the next agent or a named end. tuvl validate checks contracts, data flow, types
and policy statically and prints each workflow's determinism profile and worst-case token cost. Every
run is durable and journaled: it survives restarts, waits for people, can be paused, stepped and
steered, and can be pinned and replayed as a zero-token test fixture.
kind: Workflow
version: tuvl/v2
metadata: { name: refund_flow, description: Handle a refund request }
spec:
models: [Order, Refund]
trigger:
http: { path: /api/refunds, method: POST }
input: { order_id: uuid, reason: str }
agents:
- id: load_order
description: Load the order
engine: tool
inputs: { order_id: uuid }
outputs: { order: Order }
tool: { use: db, model: Order, op: read, where: { id: "{{ order_id }}" } }
routes: { default: triage, not_found: END.missing, error: END.failed }
- id: triage
description: Decide how the refund is handled
engine: decide
inputs: { order: Order, reason: str }
outputs: { lane: "enum[auto, review]" }
decide:
rules:
- { when: "order.total > 500", then: review }
- { when: "true", then: auto }
routes: { auto: issue_refund, review: approval, error: END.failed }
# … issue_refund (code), approval (human)
outputs:
default: { status: 200, body: { refund_id: "{{ refund.id }}" } }
missing: { status: 404, body: { error: unknown order } }
failed: { status: 500, rollback: true, body: { error: refund failed } }
Install
uv tool install "tuvl[standard]" # CLI + Insight (dev UI)
# or, in a project
uv add "tuvl[standard]"
tuvl alone is the production server; [standard] adds Insight, served only in dev mode.
Quick start
tuvl init demo --sample --preset gemini -y # a ticket-triage project with a spec, tests and a lock
cd demo
tuvl validate --strict # contracts, data flow, cost
tuvl test # offline tests
tuvl dev --auto-login # Insight at http://localhost:8885/insight
Spec-driven
tuvl spec new refund-automation # write the intent (Markdown, with checked Data and Flows)
tuvl spec check # is the spec complete and consistent? (zero tokens)
tuvl spec verify # does the implementation match it, step by step?
tuvl spec status # task statuses, derived — never typed in
tuvl codegen # schemas, code stubs, tests (no model)
The coding agent builds; tuvl referees. Every step above is deterministic and spends no tokens.
Coding agents get the same operations over MCP (tuvl mcp) and a skill set in .agents/skills/.
The CI gate:
tuvl validate --strict && tuvl codegen --check && tuvl lock --check && tuvl test && tuvl spec status --strict
Surfaces
- REST + SSE: each workflow's route,
POST /api/workflows/{name}/runs, runs, journal events, approvals, operator control; OpenAPI generated from the contracts. - MCP export:
trigger.mcp.enabledlists a workflow as a tool on/mcp. - TypeScript:
@tuvl/clientwithnpx tuvl-client generatefor typed inputs and outputs. - Insight: specs and task board, workflow canvas, runs with breakpoints, step mode and approvals, change-engine checks against pinned fixtures, judge calibration.
Production
tuvl lock && tuvl ship --tag registry/app:1.0 # gates, Dockerfile (pinned tuvl), Helm chart
tuvl run --role api # or: worker — scale HTTP and execution separately
Ed25519-signed JWT auth, default-deny triggers, scoped CRUD, approvals with no self-approval, secure fields kept away from models, optional Postgres row-level multi-tenancy.
Documentation
tuvl.dev · in this repository: agentic manual, runtime, engines, decide, loop and tools, judges, spec-driven, Insight, API, CLI, security, observability.
License & contributing
tuvl is licensed under the MIT License — see LICENSE — and will remain MIT-licensed. It is, and will stay, free to use, modify, and distribute.
Development currently happens in a private repository, so the full source is not yet publicly browsable. This is temporary: the complete codebase will be published openly in a future release. In the meantime the project is open to contribution — bug reports, feature proposals, and patches are all welcome. See CONTRIBUTING to get started, or reach out at developer@tuvl.io.
Metadata
Release files for tuvl 2.0.0b4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tuvl-2.0.0b4.tar.gz | 7.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tuvl-2.0.0b4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 8.1 MB
Release files / tuvl-2.0.0b4.tar.gz
| Download URL | tuvl-2.0.0b4.tar.gz |
|---|---|
| Size | 7.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
36077ecd3b62c2454ec810af78635c057454b1f9c5ee11202703cbfe413dcbf0
|
|
BLAKE2b-256 checksum How to use checksums |
b5258be6fb2f0bff4b1c48139291f5e562369d03560ae2d6ba402d6e020fd96d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.14
|
Release files / tuvl-2.0.0b4-py3-none-any.whl
| Download URL | tuvl-2.0.0b4-py3-none-any.whl |
|---|---|
| Size | 452.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87f306861dbd67300b20be52b5dfb38dfe397e3806e9c827d88777144b3107b9
|
|
BLAKE2b-256 checksum How to use checksums |
93fd350a15b7df50fbde5d31baef6b4d6fea5c7a239568b4665f48a6b7520dba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.14
|