Skip to content

The full journey

Use this guide to understand how Apizr turns a Python project into a service: find its functions, choose which ones to expose, generate an interface and run it.

For a first working server and verified calls, start with the Quickstart. This page explains the separate stages and their diagnostic outputs.

Install

Follow Install Apizr, then activate the core environment and check apizr --version. These guides use Apizr 0.4 and Python 3.11–3.14.

The minimal core handles static Python analysis and generation. Generated servers have their own requirements; the Quickstart installs them in a separate runtime environment. Optional analysis and delivery plugins are installed through plugin profiles. For notebook or historical pipeline dependencies, see development setup.

Walk through a small repository

Create these three files in an empty directory (also available in the repository's examples/repository-shop):

pricing.py

def total(unit_price: float, quantity: int = 1) -> float:
    return unit_price * quantity

inventory.py

def available(stock: int, requested: int = 1) -> bool:
    return stock >= requested

api.py

def quote(unit_price: float, quantity: int = 1) -> float:
    return _price(unit_price, quantity)


def _price(unit_price: float, quantity: int) -> float:
    from pricing import total

    return total(unit_price, quantity)

Save readiness-direct.json:

{"execution":{"modes":["direct"]}}

Save exposure-direct.json:

{"selection":{"include":["python:api:quote","python:inventory:available"]},"interfaces":["rest","mcp"],"execution":{"allowed":["direct"]}}

Readiness assesses whether code evidence supports an interface. The exposure policy selects the public functions and allowed modes. A bundle is the generated server, its contracts and the supporting source.

Save an operator policy for this directory before reading its source. This allows analysis only; readiness, exposure and execution policies stay independent.

python - <<'PYTHON'
import json
from pathlib import Path
root = str(Path.cwd().resolve())
Path("operator.json").write_text(json.dumps({
    "schema": "apizr.operator-policy/v1",
    "grants": [{"adapter": "repository", "operation": "analyze",
                "target": {"kind": "local", "root": root},
                "permissions": ["source.analyze"]}],
}))
PYTHON

expose build performs the analysis and generates your service in one command. The first four commands below let you inspect the intermediate results when you need to understand a selection or diagnose a refusal:

apizr scan . --operator-policy operator.json --exclude-dir .output
apizr graph . --operator-policy operator.json --exclude-dir .output
apizr readiness . --operator-policy operator.json --exclude-dir .output --policy readiness-direct.json
apizr expose plan . --operator-policy operator.json --exclude-dir .output --readiness-policy readiness-direct.json --policy exposure-direct.json
apizr expose build rest . --operator-policy operator.json --exclude-dir .output --readiness-policy readiness-direct.json --policy exposure-direct.json --output-dir .output/rest
apizr expose build mcp . --operator-policy operator.json --exclude-dir .output --readiness-policy readiness-direct.json --policy exposure-direct.json --output-dir .output/mcp

The explicit .output exclusion keeps generated files outside the scan universe. Readiness reports three ready functions and one conditional support helper, so its exit code is 1. The two explicitly selected public functions are eligible; planning and building succeed. READY does not mean exposed. pricing.total is packaged and called through api._price, but neither helper is public.

Serve the direct REST bundle:

python3 -m venv .output/runtime
.output/runtime/bin/python -m pip install -r .output/rest/requirements.txt
.output/runtime/bin/uvicorn app:app --app-dir .output/rest --host 127.0.0.1 --port 8000

POST {"unit_price":12.5,"quantity":2} to /capabilities/api.quote → 25.0. POST {"stock":10,"requested":3} to /capabilities/inventory.available → true. The separate runtime environment keeps server dependencies out of Apizr's core. The MCP bundle exposes the same two names; follow the MCP client steps with .output/mcp as your bundle directory. These servers execute trusted code. Use a fresh output directory when regenerating.

Understand the decisions

Layer Responsibility
Repository Readiness policy Assess evidence and compatible execution contracts
Exposure policy Explicitly select public capability IDs, interfaces and allowed modes
Execution policy Configure the one actual worker backend and its required controls

READY does not mean exposed. The graph describes relationships; it does not publish their targets. Here api.quote calls private support code in pricing.py. Only api.quote and inventory.available appear in REST/MCP.

Choose your next step

Task Guide
Inventory a repository Scanner and catalog
Understand relationships Capability graph
Inspect one script or notebook Static inspection
Assess eligibility Repository readiness
Select and expose a repository Exposure and policy examples
Use fresh local/OCI workers Governed repository execution
Keep single-source workflows REST / MCP
Use the historical notebook/script pipeline Legacy guide

Direct state persists in the transport interpreter. Governed local state resets in a fresh process per call; governed OCI state resets in a fresh container per call. Local execution provides bounds/environment/cleanup, not filesystem or network isolation. OCI uses reviewed container controls and offers an optional strict subprocess-deny profile; it is not a VM. Both require trusted source and dependencies; neither is an automatic untrusted-code guarantee. Architecture and boundaries.

Compatibility and limits

Modern single-source inspect, generate rest/mcp and execute commands remain supported alongside repository workflows. They are not the legacy pipeline. The historical apizr --script / --notebook pipeline is a separate path; there is no automatic migration or publication.

Public capabilities remain top-level functions. Class/method exposure and an enterprise control plane are not supported. Repository bundles do not infer or install application dependencies or package arbitrary repository data files. The legacy pipeline supports explicit requirements and resources, configured notebook cell selection, explicit image builds and installed pipeline plugins. It inventories classes and methods separately and refuses ambiguous selected definitions/overloads. See the notebook configuration guide.

Static readiness/exposure v1 adapters keep their original control vocabulary; the strict OCI profile is selected through an execution policy, which chooses the actual worker backend and its required controls. See compatibility notes.