Orcha AI extraction.
- Docker & Docker Compose
- uv (Python package manager)
- Python ≥ 3.14
uv syncSQLite is the local-development default, so no Docker services are required.
orcha run applies migrations against a local orcha.db file, starts a
Temporal dev server backed by temporal.db, then the API and a worker:
uv run orcha runThis requires the temporal CLI to
be installed. Stopping it (Ctrl-C) preserves both database files; pass
--reset to delete them first and start from a clean state:
uv run orcha run --resetTo use PostgreSQL instead (e.g. to match production), start the Dockerized services, point the app at them, and run the API and worker as separate processes:
uv run orcha services start
export DB_DIALECT=postgresql # DB_USER/DB_PASSWORD/DB_HOST/DB_PORT/DB_NAME
# default to the docker-compose values
uv run orcha migrate
uv run orcha run server --dev # FastAPI dev server
uv run orcha run workers # Temporal worker for the default queue
# Run a worker for a specific queue
uv run orcha run workers --task-queue low-priorityThe API uses multi-tenant RS256 (asymmetric) JWT authentication. Each tenant has its own RSA key pair(s). The tenant signs tokens with their private key; the server verifies them using the tenant's registered public key.
Tenants are identified by the iss (issuer) claim in the JWT. To support zero-downtime key rotation, the server allows multiple public keys per tenant. In token headers, tenants must include a Key ID (kid) that matches one of their defined keys in the configuration.
orcha run sets DEV_MODE, which turns authentication off: no token is
required and every request runs as the dev tenant, so tenant scoping behaves
the same as it does anywhere else.
uv run orcha run
curl http://localhost:8000/AUTH_DISABLED overrides that either way, so AUTH_DISABLED=0 uv run orcha run
exercises real tenant tokens against the local stack.
See Running against a local InvenioRDM for pointing an instance at a local Orcha.
Real tenants live in tenants.json (override with TENANTS_CONFIG_PATH), keyed
by the iss claim their tokens carry:
{
"tenant-a": {
"name": "Tenant A",
"public_keys": {
"kid-1": "-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----"
}
}
}A tenant generates its own key pair and sends you the public half:
uv run orcha tenants add tenant-a ./their_public_key.pem
uv run orcha tenants listPass --kid to register a second key alongside the first, and --force to
replace one. orcha tenants token tenant-a ./private_key.pem signs a token from
the tenant side, with --kid to pick the key, --workflow-id to scope it to
one workflow and --expires-in to set its lifetime in seconds.
⚠️ Never committenants.jsonor.pemfiles — they are already in.gitignore.
| Variable | Description | Required |
|---|---|---|
JWT_ALGORITHM |
Signing algorithm (default: RS256) | No |
DEV_MODE |
Run as the dev tenant with auth off |
Development |
AUTH_DISABLED |
Override the auth switch either way | Development |
TENANTS_CONFIG_PATH |
Path to tenants JSON (default: tenants.json) | Production |
The service supports multiple LLM backends. Configure a single setting, LLM,
in the form <provider>/<model>.
export LLM="litellm/groq/qwen/qwen3-32b"Optional configuration:
export LITELLM_API_BASE="<litellm-endpoint>"
export LITELLM_API_KEY="<api-key>"export LLM="ollama/llama3.1"
export OLLAMA_BASE_URL="http://localhost:11434/v1"| Command | Description |
|---|---|
orcha services start |
Start PostgreSQL + Temporal via Docker |
orcha services stop |
Stop all Docker services |
orcha migrate |
Apply all database migrations |
orcha run |
Migrate, then start Temporal, API, and worker (SQLite) |
orcha run --reset |
Same, after deleting orcha.db and temporal.db |
orcha run server |
Start the FastAPI server only |
orcha run server --dev |
Start the FastAPI server with hot reload |
orcha run workers |
Start Temporal worker for default queue |
orcha run workers --task-queue Q |
Start Temporal worker for a specific queue |
orcha tenants list |
List registered tenants and their key IDs |
orcha tenants add T KEY.pem |
Register a tenant's public key |
orcha tenants token T KEY.pem |
Sign a token for a tenant |
The deployed schema is managed with Alembic. Apply committed migrations with:
uv run alembic upgrade headFor local setup, uv run orcha migrate is a convenience wrapper around the
same Alembic upgrade.
See Database Migrations for the full process of generating and reviewing migrations when SQLModel models change.
# Stop and remove volumes (reset databases)
docker compose down -v
# View Docker service logs
docker compose logs -f
# Open Temporal UI
open http://localhost:8080Release for Orcha are done manually. Pushing a v* tag triggers the image build, so commit the version bump and changelog before you tag.
Bump pyproject.toml and re-lock in one step:
uv version --bump patch # or: minor, majorThen set the same X.Y.Z in charts/orcha/Chart.yaml, in both version and appVersion.
CHANGELOG.md follows Keep a Changelog. Every feat:/fix:/refactor: commit should already have a bullet under ## [Unreleased]. At release time, promote that section:
- Rename
## [Unreleased]to## [X.Y.Z] - YYYY-MM-DDand open a fresh empty## [Unreleased]above it. - In the link footer, repoint
[unreleased]tovX.Y.Z...HEADand add[X.Y.Z]: .../compare/<prev>...vX.Y.Z.
git commit -am "release: vX.Y.Z"
git tag vX.Y.Z
git push origin main vX.Y.ZThe tag push kicks off the Docker workflow below, which builds and publishes the image.
Docker images are automatically built and published to registry.cern.ch/orcha/orcha by the Docker workflow.
| Event | Image tag |
|---|---|
Push a v* tag (e.g. v1.2.3) |
1.2.3 |
Manual via GitHub UI (workflow_dispatch) |
depends on branch/tag |
The workflow uses two repository secrets that must be configured in Settings → Secrets and variables → Actions:
| Secret | Description |
|---|---|
REGISTRY_USER |
registry robot account username |
REGISTRY_PASSWORD |
registry robot account password |