Metadata-Version: 2.5
Name: tuvl
Version: 2.0.0b9
Summary: 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
Project-URL: Homepage, https://tuvl.io
Project-URL: Documentation, https://tuvl.dev
Project-URL: Repository, https://github.com/tuvl-io/tuvl
Project-URL: Changelog, https://github.com/tuvl-io/tuvl/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/tuvl-io/tuvl/issues
Author-email: "tuvl.io" <developer@tuvl.io>
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: agents,ai,backend,fastapi,llm,mcp,orchestration,spec-driven,workflow,yaml
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: <3.15,>=3.13
Requires-Dist: asyncpg>=0.31.0
Requires-Dist: bcrypt>=5.0.0
Requires-Dist: cronsim>=2.7
Requires-Dist: cryptography>=43.0.0
Requires-Dist: fastapi>=0.136.0
Requires-Dist: greenlet>=3.4.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: opentelemetry-api>=1.42.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.42.0
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.63b0
Requires-Dist: opentelemetry-sdk>=1.42.0
Requires-Dist: pydantic-settings<3,>=2.14.1
Requires-Dist: pydantic<3,>=2.13.4
Requires-Dist: pyjwt[crypto]>=2.10.0
Requires-Dist: python-dotenv<2,>=1.2.2
Requires-Dist: python-multipart>=0.0.12
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: rich>=15.0.0
Requires-Dist: sqlalchemy[asyncio]<2.1,>=2.0
Requires-Dist: sqlmodel>=0.0.38
Requires-Dist: starlette>=0.49.0
Requires-Dist: structlog>=24.0.0
Requires-Dist: typer<0.27,>=0.26.5
Requires-Dist: uvicorn[standard]>=0.44.0
Provides-Extra: codegen
Requires-Dist: libcst>=1.4; extra == 'codegen'
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.27.0; extra == 'mcp'
Provides-Extra: otel-grpc
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.42.0; extra == 'otel-grpc'
Provides-Extra: pdf
Requires-Dist: pypdf>=5.0; extra == 'pdf'
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == 'redis'
Provides-Extra: review
Requires-Dist: ruff>=0.8; extra == 'review'
Provides-Extra: standard
Requires-Dist: aiosqlite>=0.20.0; extra == 'standard'
Requires-Dist: libcst>=1.4; extra == 'standard'
Requires-Dist: mcp<2,>=1.27.0; extra == 'standard'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.42.0; extra == 'standard'
Requires-Dist: pgvector>=0.3.0; extra == 'standard'
Requires-Dist: pypdf>=5.0; extra == 'standard'
Requires-Dist: redis>=5.0.0; extra == 'standard'
Requires-Dist: ruff>=0.8; extra == 'standard'
Requires-Dist: textual>=1.0; extra == 'standard'
Requires-Dist: tuvl-insight>=2.0.0b9; extra == 'standard'
Provides-Extra: test
Requires-Dist: aiosqlite>=0.20.0; extra == 'test'
Provides-Extra: tui
Requires-Dist: textual>=1.0; extra == 'tui'
Provides-Extra: vector
Requires-Dist: pgvector>=0.3.0; extra == 'vector'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/tuvl-io/tuvl/main/assets/logo.png" alt="" width="40" />&nbsp;&nbsp;<span style="font-size:2em"><strong>tuvl</strong></span><br/>
  <sub>/ˈtuːvəl/ &nbsp;·&nbsp; തൂവൽ &nbsp;·&nbsp; feather</sub>
</p>

<p align="center">
  Typed workflows of agents — code, database/HTTP/MCP tools, rules, models,<br/>
  bounded tool loops and people — on a durable, journaled runtime,<br/>
  built spec-first and served as REST, SSE and MCP.
</p>

<p align="center">
  <a href="https://tuvl.io">Website</a> &nbsp;·&nbsp;
  <a href="https://tuvl.dev">Docs</a> &nbsp;·&nbsp;
  <a href="https://github.com/tuvl-io/tuvl">GitHub</a>
</p>

> **tuvl 2.0** is a redesign with no 1.x compatibility layer — see the
> [CHANGELOG](CHANGELOG.md). Versions follow [SemVer](https://semver.org).

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, blob storage 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 |
| `map` | a workflow run once for every item of a list | as the child |
| `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 lint project` 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.

```yaml
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

```bash
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, and the
development tools (`tuvl generate code`, `tuvl run tests`, `tuvl serve mcp`). Features with their own packages are
extras: `tuvl[mcp]`, `tuvl[redis]`, `tuvl[vector]`, `tuvl[otel-grpc]`. `tuvl ship` installs only the ones a project uses.

## Quick start

```bash
tuvl init demo --sample --preset gemini -y     # a ticket-triage project with a spec, tests and a lock
cd demo
tuvl lint project --strict                         # contracts, data flow, cost
tuvl run tests                                      # offline tests
tuvl dev --auto-login                          # Insight at http://localhost:8885/insight
```

## Spec-driven

```bash
tuvl create spec refund-automation      # write the intent (Markdown, with checked Data and Flows)
tuvl lint spec                      # is the spec complete and consistent? (zero tokens)
tuvl verify spec                     # does the implementation match it, step by step?
tuvl list tasks                     # task statuses, derived — never typed in
tuvl generate code                         # 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 serve mcp`) and a skill set in `.agents/skills/`.

The CI gate:

```bash
tuvl lint project --strict && tuvl generate code --check && tuvl verify lock && tuvl run tests && tuvl list tasks --strict
```


## Authoring with your coding agent

Already have Claude Code, Codex or Gemini CLI? tuvl can drive it from an idea to a packaged project, and
accept only what its own checks (no model in the loop) pass:

```bash
tuvl import idea brief.pdf           # IDEA-SK-0004: a numbered, immutable copy of the brief
tuvl generate spec --idea IDEA-SK-0004    # your agent drafts SPEC-SK-0004-01 on a branch; a person approves it
tuvl approve spec SPEC-SK-0004-01 && tuvl generate tasks SPEC-SK-0004-01
tuvl generate code --spec SPEC-SK-0004-01 --all   # models and skeletons first, then your agent, one PR per task
tuvl review code && tuvl ship --format both      # gate, image and a runnable archive
```

`tuvl dev` shows the same path in a terminal UI, and every step is in a local audit ledger. Details:
[docs/authoring.md](docs/authoring.md).

## 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.enabled` lists a workflow as a tool on `/mcp`.
- **TypeScript:** [`@tuvl/client`](https://www.npmjs.com/package/@tuvl/client) with
  `npx tuvl-client generate` for 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

```bash
tuvl generate lock && tuvl ship --tag registry/app:1.0    # gates, Dockerfile (pinned tuvl + only the extras you use), Helm chart
tuvl serve app --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](https://tuvl.dev) · in this repository: [agentic manual](docs/tuvl-agentic-manual.md),
[runtime](docs/runtime.md), [engines](docs/engines.md), [decide](docs/decide.md),
[loop and tools](docs/loop-and-tools.md), [judges](docs/judges.md),
[storage](docs/storage.md), [models](docs/models.md), [spec-driven](docs/spec-driven.md), [Insight](docs/insight.md), [API](docs/api.md),
[CLI](docs/cli.md), [security](docs/auth.md), [observability](docs/observability.md).

---

## License & contributing

tuvl is licensed under the **Apache License, Version 2.0** — see [LICENSE](LICENSE) and
[NOTICE](NOTICE). It is free to use, modify and distribute, with an express patent grant.
The name "tuvl" and the logos are not licensed for use as a brand (Apache-2.0 §6).

Releases up to and including `2.0.0b4` were published under the MIT License and remain available
under it. Starting with `2.0.0b5` tuvl is Apache-2.0; see the [changelog](CHANGELOG.md).

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](CONTRIBUTING.md) to get started, or reach out at
[developer@tuvl.io](mailto:developer@tuvl.io).
