The Python bridge/The Python execution model

The Python execution model

Runtime, dev versus production, and deployment.

Runtime

When a BionicJS project includes Python capabilities (AI, Jobs), bionicjs dev spawns a Python child process. This process runs a FastAPI server that handles RPC calls from the Nitro server.

Process topology
1bionicjs dev
2  |-- Vite (:3000)          # the React client
3  |-- Nitro (:3001)         # the API / h3 handlers
4  `-- Python (internal)     # FastAPI RPC surface (only when ai//jobs/ exist)

The Python process is started and managed by the dev orchestrator. It picks up its dependencies from pyproject.toml, and it is torn down cleanly when the dev server exits. The developer never starts it separately.

The FastAPI server is the RPC surface, not a public API. It is reached from Nitro over an internal channel - never from the browser. There is no CORS, no OAuth flow, and no public route for the browser to hit.

Dev versus production

Everything about the Python process is environment-dependent:

ConcernDevelopmentProduction
ProcessSpawned by bionicjs devSupervised (container / systemd)
ChannelInternal localhostSame container or private network
DependenciesInstalled on demandLocked in pyproject.toml / lockfile
FailuresLogged to unified terminalContainer restart policy

Key management is the same in both environments: each provider template writes its expected variables into .env.example, and the Python code reads them from the environment.

Deployment

In production, the deployment model can either run both Node.js and Python in the same container, or split them into separate microservices communicating over a private network. BionicJS generates the Dockerfiles and configurations to support either model.

Two deployment shapes
1same unit                     split services
2+--------------+              +---------+   +---------+
3| nitro server |  <--Python-> | nitro   |   | fastapi |
4| python proc  |              | server  |<->| worker  |
5+--------------+              +---------+   +---------+
6   simpler                        cloud-native scale-outs
ⓘ
The RPC contract is the same in both shapes. The only change between "same container" and "microservices" is where the Python process runs - the generated client points at a local socket in one case and a private network address in the other. Your code does not change.