English · 简体中文
One API to run all light-weight decision models.
Decis is a self-hostable inference server for open decision models. It implements the
TypeSafe System One API — the /v1/systemone contract the
official typesafe-sdk already speaks — so pointing the SDK at your own host is the whole
migration. One wire contract, several interchangeable engines, one container per engine.
A decision model returns calibrated probabilities for typed questions instead of generating text: one forward pass, small enough to run next to your app.
- Runs out of the box. Three commands and you have an engine answering
/v1/systemoneand a playground to try it in. The images carry their weights, so nothing is downloaded at startup and there is no volume to mount. - A Jev-like API. Decis speaks the contract the closed model does, so the official
typesafe-sdkneedsbase_urlchanged and nothing else. - Laya and kev, one image each. A published multi-arch image per engine, weights included.
- A playground with three games. Snake, dino and tetris, each one deciding through a
real
/v1/systemonecall.
Status: pre-1.0, currently
v0.3.0. The wire contract (v1) is stable and only gains fields; the running server reports its own version at/healthz.
Three commands, no build and no model download:
git clone https://github.com/chaitin/Decis && cd Decis
cp .env.example .env # set DECIS_API_KEY
docker compose -f docker-compose.yml up -d --wait # engine on :8000, games on :8080laya-multilingual is the default engine. /healthz answers immediately; /readyz reports
loading until the model can answer:
until curl -fsS localhost:8000/readyz >/dev/null; do sleep 2; doneThe client side is one changed line. The official SDK works unchanged once it points here:
from typesafe_sdk import Choice, Noul, TypeSafeClient
# No `model=`: the SDK sends its default, "jev-latest", and Decis answers with the
# engine it is actually running. Swapping base_url is the whole migration.
client = TypeSafeClient(api_key="local", base_url="http://127.0.0.1:8000")
response = client.system_one(
state={
"subject": "Duplicate charge on invoice #4411",
"body": "We were billed twice for March. Refund it today or we cancel our plan.",
},
questions={
"department": Choice(
instructions="Which team should handle this?",
criteria={
"billing": "invoices, payments, refunds",
"technical": "bugs, outages, system errors",
"sales": "pricing, new contracts",
},
),
"churn_risk": Noul(instructions="Does the user threaten to cancel or leave?"),
},
)
print(response.choices["department"].choice) # one of the criteria keys
print(response.choices["department"].confidence) # 0..1
print(response.nouls["churn_risk"].noul) # P(true), 0..1Compose pulls two published images, chaitin/decis:laya-multilingual and
chaitin/decis:playground. To run the API without Compose:
docker run --rm -p 8000:8000 -e DECIS_API_KEY=change-me chaitin/decis:laya-multilingualFrom a source checkout instead:
uv sync --extra dev --extra laya
uv run decis download --engine laya-multilingual # 647 MiB, once
uv run decis serve --host 127.0.0.1 --port 8000Getting started covers readiness, the raw curl form, and
decis models / decis doctor.
Four engines ship. laya-multilingual (the default, about 100 languages) and kev-0.8b
have published multi-arch images; laya and laya-typed-decisions run from a source
checkout. One image per engine, the engine is the tag, and the weight files are inside it —
no network, no volume and no download step at startup. The server requires a bearer token,
compares it in constant time, and refuses to start on a public address with no token
configured.
Backbones, weight sizes and per-engine limits are in Engines. Pull sizes, the weightless runtime variant, Kubernetes probes and building behind a proxy are in Deployment.
The Quickstart also starts three browser games at http://localhost:8080 — snake, dino and
tetris — plus a reference page for the API itself at /api. Each one can be played by hand
from the keyboard or handed to the model: the manual/AI switch, the inference panel and the
console for the last call are the same on all three, and in AI mode every decision is one
real /v1/systemone call. The playground holds the API key server-side, so the pages never
see it, and it finds the engine by itself. See Playground, including
the projects the games are adapted from.
Each recording is that page in AI mode, against a real engine on CPU. Unchanged frames are dropped.
| Snake | Dino | Tetris |
|---|---|---|
![]() |
![]() |
![]() |
| Document | What it covers |
|---|---|
| Getting started | Clone to first answer, readiness, CLI |
| API reference | Endpoints, schemas, primitives, error codes, limits |
| API schemas | Generated JSON Schema and the server's OpenAPI document |
| Configuration | Every DECIS_* variable, auth, model paths, dtype |
| Engines | What each engine is, its limits, how to add one |
| Deployment | Docker, Compose, make, Kubernetes |
| Performance | Measured latency and memory, on the machine they were measured on |
| Playground | The three games, the proxy, and credits |
| Wire contract | The exact jev contract, with an evidence level per claim |
| Design | Architecture, the engine abstraction, packaging |
| Design review | A self-audit: defects found, methodology limits, what is unverified |
| Feasibility | Investigation results and the risk register |
examples/ |
Runnable curl and official-SDK examples, executed by CI |
| AGENTS.md | Engineering contract for contributors and agents |
The wire contract, the design, its self-audit and the feasibility study are written in
Chinese; the contract is also pinned as generated JSON Schema under
docs/schema/, generated from src/decis/schema.py and checked in CI.
- Jev (TypeSafe AI) — the closed model whose API this project targets. Decis reimplements the interface, not the model.
- kev (Jared Palmer) — a Jev-style decision model
built on Qwen3.5. Decis reuses kev's inference kernel (vendor-pinned, Apache-2.0,
attributed in
NOTICE) and generalises the serving layer to many engines. - Laya (Convai Innovations) —
Apache-2.0, multilingual, one forward pass. Decis uses the official
layapackage. - djev-run (Daniel Lee) — the playground's games are adapted from it; see Playground.
Contributions are welcome. CONTRIBUTING.md covers the development
setup, the two test environments, and the pull-request rules; AGENTS.md is
the normative engineering contract — canonical homes, invariants and banned patterns — and
applies to human and automated contributors alike.
uv sync --extra dev
uv run pytest -q # the weight-free suite: what CI runs
uv run ruff check && uv run ruff format --checkSecurity issues should go through SECURITY.md, not a public issue.
Apache-2.0. See NOTICE for third-party attribution.


