Base application¶
The orchestrator-core is a standalone API with a workflow engine and database, similar to frameworks like FastAPI, Flask and Django. You install the core library, initialise it with configuration and run.
Note
The Orchestrator-core is designed to be installed and extended just like a FastAPI or Flask application. For more information about how this works read the Reference documentation.
Quick start with the cookiecutter¶
The fastest way to start a new orchestrator is with the orchestrator-cookiecutter. It generates a complete project: source layout, database migrations, Celery worker (optional), docker-compose (optional), test infrastructure and pre-commit hooks— all with one command.
Prerequisites¶
uv(Python package manager)- A PostgreSQL database (>= 15 with pgvector)
- Docker (optional, for running Postgres and Redis locally)
Step 1 - Generate the project¶
$ uvx orchestrator-cookiecutter
# [1/8] project_name (My Orchestrator): $ My Orchestrator
# [2/8] project_slug (my_orchestrator): $ my_orchestrator
# [3/8] package_name (my-orchestrator): $ my-orchestrator
# [4/8] description: $ A Workflow Orchestrator implementation for My Orchestrator.
# [5/8] author (ACME inc.): $ ACME inc.
# [6/8] author_email (devnull@example.com): $ devnull@example.com
# [7/8] executor [1-Threadpool, 2-Celery] (1): $ 2
# [8/8] Generate docker-compose.yml? [1-yes, 2-no] (1): $ 1
// Installing dependencies, git repo, pre-commit hooks, DB migrations...
---> 100%
========== Completed cookiecutter install ===========
The wizard asks for a project name, executor type (Threadpool or Celery) and whether to generate a
docker-compose.yml. It then installs dependencies, initialises a git repository with pre-commit
hooks, and creates the Alembic migration environment.
Tip
Choose Threadpool to get started quickly. You can switch to Celery later by adding
a celery_worker.py and setting EXECUTOR=celery; see
Scaling the Orchestrator.
Step 2 - Start the database¶
If you chose to generate a docker-compose.yml:
cd my-orchestrator
docker compose up -d
Otherwise, point the app at your own PostgreSQL database:
export DATABASE_URI=postgresql+psycopg://<user>:<password>@<host>:<port>/<database>
The server needs pgvector; see Postgres with pgvector.
Step 3 - Create the database schema¶
The migration environment (migrations/, alembic.ini) was already generated for you, so there is
no need to run db init. main.py lives in the package directory (e.g. my_orchestrator/):
cd my_orchestrator && uv run main.py db upgrade heads
Step 4 - Run the app¶
uv run uvicorn --reload --host 127.0.0.1 --port 8080 my_orchestrator.wsgi:app
Visit the OpenAPI docs or ReDoc to interact with the API.
Step 5 - Run the tests¶
$ uv run pytest
What the cookiecutter generates¶
my-orchestrator/
├── my_orchestrator/
│ ├── __init__.py # init_app() and init_cli_app()
│ ├── main.py # CLI entrypoint
│ ├── wsgi.py # ASGI entrypoint (uvicorn)
│ ├── celery_worker.py # Celery worker (when chosen)
│ ├── products/ # Product types and blocks
│ ├── workflows/ # Workflow registrations
│ ├── services/ # Business logic
│ ├── utils/
│ ├── translations/ # UI translation strings
│ └── migrations/ # Alembic migration environment
├── test/ # Test infrastructure with transactional rollback
├── pyproject.toml
├── docker-compose.yml # Postgres + Redis (when chosen)
├── .pre-commit-config.yaml
└── README.md
Next¶
- Create a workflow for a product.
- Generate products and workflows
- Run your orchestrator in containers or on Kubernetes
Manual setup¶
Setting up a project without the cookiecutter
If you prefer to set up a project manually, or need to understand what the cookiecutter does under the hood, follow these steps. The cookiecutter generates equivalent code for all of them.
Step 1 - Install the package¶
Create a virtualenv and install the core.
uv init my-orchestrator
cd my-orchestrator
uv add orchestrator-core
source .venv/bin/activate
python -m venv .venv
source .venv/bin/activate
pip install orchestrator-core
Step 2 - Setup the database¶
Create a postgres database:
$ createuser -sP nwa
$ createdb orchestrator-core -O nwa
Choose a password and remember it for later steps. The server needs pgvector; see Postgres with pgvector.
As an example, you can run these docker commands in separate shells to start a temporary postgres instance:
docker run --rm --name temp-orch-db -e POSTGRES_PASSWORD=rootpassword -p 5432:5432 pgvector/pgvector:pg17
docker exec -it temp-orch-db su - postgres -c 'createuser -sP nwa && createdb orchestrator-core -O nwa'
Step 3 - Create the main.py and wsgi.py¶
Create a main.py file.
This provides the CLI entrypoint to your Orchestrator.
import typer
from nwastdlib.logging import initialise_logging
from orchestrator.core import app_settings
from orchestrator.core.cli.main import app as core_cli
from orchestrator.core.db import init_database
from orchestrator.core.log_config import LOGGER_OVERRIDES
def init_cli_app() -> typer.Typer:
initialise_logging(LOGGER_OVERRIDES)
init_database(app_settings)
return core_cli()
if __name__ == "__main__":
init_cli_app()
import typer
from nwastdlib.logging import initialise_logging
from orchestrator import app_settings
from orchestrator.cli.main import app as core_cli
from orchestrator.db import init_database
from orchestrator.log_config import LOGGER_OVERRIDES
def init_cli_app() -> typer.Typer:
initialise_logging(LOGGER_OVERRIDES)
init_database(app_settings)
return core_cli()
if __name__ == "__main__":
init_cli_app()
Create a wsgi.py file.
This will be used to run the Orchestrator API.
from orchestrator.core import OrchestratorCore
from orchestrator.core.settings import app_settings
app = OrchestratorCore(base_settings=app_settings)
app.register_graphql()
from orchestrator import OrchestratorCore
from orchestrator.settings import app_settings
app = OrchestratorCore(base_settings=app_settings)
app.register_graphql()
Step 4 - Run the database migrations¶
Initialize the migration environment and database tables.
$ export DATABASE_URI=postgresql+psycopg://nwa:PASSWORD_FROM_STEP_2@localhost:5432/orchestrator-core
$ python main.py db init
$ python main.py db upgrade heads
Step 5 - Run the app¶
$ export DATABASE_URI=postgresql+psycopg://nwa:PASSWORD_FROM_STEP_2@localhost:5432/orchestrator-core
$ export OAUTH2_ACTIVE=False
$ uvicorn --reload --host 127.0.0.1 --port 8080 wsgi:app
Step 6 - Verify¶
Visit the ReDoc or OpenAPI to view and interact with the API.