Skip to main content

Tenchi

CI PyPI Python

Typed Python APIs with explicit boundaries and plain application code.

Tenchi keeps Pydantic validation at the boundary, behavior in plain async functions, and infrastructure behind typing.Protocol ports. A contract describes an HTTP operation; route() binds it to a use case; your application wires the dependencies.

There is no dependency-injection container, base controller, ORM, queue, scheduler, or model runtime hidden inside the framework.

Pre-1.0 software. Minor releases may change public APIs. Read stability and releases before adopting Tenchi for a long-lived service.

Documentation · First application · How Tenchi works

Build and run an application

Tenchi requires Python 3.12 or newer. Create a working application with uv:

uvx tenchi new my_app
cd my_app
uv sync
uv run tenchi check
uv run tenchi dev

Call the generated todos API from another terminal:

curl -i \
  -H 'content-type: application/json' \
  -d '{"title":"Buy milk"}' \
  http://127.0.0.1:8000/todos

Open Swagger UI to inspect and call the same API in a browser. The first-application guide follows this request through the generated code and makes one behavior change.

The application model

Every HTTP operation follows the same path:

validated input -> contract + route -> async use case -> app-owned port -> adapter

A Pydantic model defines the boundary data:

# app/features/todos/schemas.py
from pydantic import BaseModel, Field


class CreateTodo(BaseModel):
    title: str = Field(min_length=1)


class Todo(BaseModel):
    id: str
    title: str
    completed: bool

A contract declares the HTTP operation:

# app/features/todos/contracts.py
from tenchi.contracts import contract

from .schemas import CreateTodo, Todo


create_todo_contract = contract(
    method="POST",
    path="/todos",
    request=CreateTodo,
    response=Todo,
    status=201,
)

The use case contains the behavior. Its context is an application-owned frozen dataclass, so dependencies stay visible and type checked:

# app/features/todos/use_cases/create_todo.py
from app.server.context import AppContext

from ..schemas import CreateTodo, Todo


async def create_todo(request: CreateTodo, context: AppContext) -> Todo:
    return await context.todos.create(title=request.title)

The route makes the binding explicit:

# app/features/todos/routes.py
from tenchi.routes import route, route_group

from .contracts import create_todo_contract
from .use_cases.create_todo import create_todo


routes = route_group(
    route(create_todo_contract, create_todo),
)

route() checks the function signature during application composition. At runtime, Tenchi validates input before the use case and validates its result before the request scope commits. The same contract can also drive OpenAPI and the typed Python client.

JSON responses are checked against their published schema and read back through Pydantic before committing, including when a use case returns an existing model. Response field aliases must be readable by that same model; use Field(alias=...) for shared wire names. See successful responses.

Read How Tenchi works for the complete mental model or Build a feature to carry an operation through persistence and tests.

Add capabilities when you need them

The core model stays the same as the application grows:

These features are independent. A Tenchi application does not need jobs, AI tools, evaluations, or historical compatibility checks to define and serve an HTTP API.

When Tenchi fits

Choose Tenchi when you want a long-lived typed JSON API with explicit dependencies, directly testable behavior, and boundary definitions that stay aligned with OpenAPI and client code.

Choose another framework when you need WebSockets, HTML templates, an ORM, admin UI, background runtime, or a large integration ecosystem as built-in features. The framework comparison describes the tradeoffs with FastAPI, Starlette, Litestar, and Django Ninja.

Development

uv sync
uv run ruff format --check .
uv run ruff check .
uv run pyright
uv run pytest

The documentation is a separate Next.js application in docs/. Run bun install and bun run check from that directory to lint, type-check, test, and build the static site.

Tenchi is available under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tenchi-0.17.0.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tenchi-0.17.0-py3-none-any.whl (274.1 kB view details)

Uploaded Python 3

File details

Details for the file tenchi-0.17.0.tar.gz.

File metadata

  • Download URL: tenchi-0.17.0.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tenchi-0.17.0.tar.gz
Algorithm Hash digest
SHA256 28a80aa2dbf682e5daed4d989a22216f4999bb2e9fdafaf5700fe9549f50a14d
MD5 e93e079a0bdf30f500b3e0ea385ee1cd
BLAKE2b-256 d9ec75e3e48d41fc39ea90fee374f1db1c1268219db82b89a2e6a225c1778dbc

See more details on using hashes here.

File details

Details for the file tenchi-0.17.0-py3-none-any.whl.

File metadata

  • Download URL: tenchi-0.17.0-py3-none-any.whl
  • Upload date:
  • Size: 274.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tenchi-0.17.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2e99479f543ff0816506e17e95afcadb3591977e4e399f4930fef41bb76cfb2d
MD5 1a219592f92db467bb6503149f8dc96b
BLAKE2b-256 b3aac5e48e98a7ffa9c026ee24a58b0c7bfd7ce2af26955b5875d6c1fcba3169

See more details on using hashes here.

Release history Release notifications | RSS feed

0.18.0

2 files

This release

0.17.0 This release

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page