Skip to main content

Supervaizer

Created: 2024-12-28 Updated: 2026-10-05

Supervaizer is the Python controller SDK for exposing AI agents to Supervaize Studio through the Supervaizer v2 operation contract.

Supervaizer v2 is layered on:

  • A2A for discovery, Agent Cards, JSON-RPC controller calls, and SSE events
  • A2UI for agent-authored UI surface documents rendered by Studio
  • Supervaizer v2 semantics for Jobs, Cases, Steps, Resources, Datasets, Surfaces, Actions, Artifacts, and job.sync convergence

Supervaizer does not contain agent business logic. Agents declare their resources, surfaces, actions, and artifacts; Studio consumes that declaration as a generic operations UI.

Beta: Supervaizer v2 is under active development. Protocol versions are pinned in the registration contract and incompatible versions should fail explicitly.

Start Here

Quick Start

1. Install

pip install supervaizer

For local development from this repository:

just install-dev   # uv sync --extra dev

2. Run The Built-In V2 Hello World Agent

The fastest way to see the v2 controller is local mode:

supervaizer start --local

Local mode runs the agents from your supervaizer_control.py plus the built-in Hello World agent (disable it with SUPERVAIZER_DISABLE_HELLO_WORLD=true); with no control file it starts Hello World alone. Hello World declares:

  • a v2 Agent Card
  • job.start and case.step.awaiting A2UI surfaces
  • job.start, job.start.preview, job.sync, and step.awaiting.submit actions
  • one generated resource action, resource.hello_messages.list
  • a minimal HITL review step when human review is enabled

Local mode binds to 127.0.0.1, skips Studio registration, and uses the API key local-dev. It also bypasses Studio workspace authorization for /a2a actions and surfaces, so X-API-Key alone is enough:

curl -s http://127.0.0.1:8000/a2a \
  -H "X-API-Key: local-dev" -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "supervaizer/action.invoke",
       "params": {"request_id": "r1", "actor": {"user_id": "me"},
                  "workspace": {"id": "local"}, "mission_id": "m1",
                  "agent_slug": "hello-world-ai-agent", "surface": "job.start",
                  "action": "job.start", "input": {"count": 1}, "job_id": "job-1"}}'

Handlers receive an unverified workspace_authorization whose grant_id is local-mode, and the server logs a startup warning. The bypass applies only while the server has no Studio account and none of SUPERVAIZER_WORKSPACE_AUTH_REQUIRED, _ISSUER, _AUDIENCE, _PUBLIC_KEY, or _JWKS_URL is set. Otherwise every call needs a real Studio token, and a partial setup answers workspace_authorization_not_configured. Never expose a local-mode port: anyone who reaches it can run your agents with the well-known key.

Open these endpoints:

URL Purpose Access
http://127.0.0.1:8000/docs FastAPI Swagger docs public
http://127.0.0.1:8000/.well-known/agents.json A2A discovery public
http://127.0.0.1:8000/.well-known/health Controller health public
POST http://127.0.0.1:8000/a2a A2A JSON-RPC controller endpoint X-API-Key (write scope); workspace token outside local mode
GET http://127.0.0.1:8000/a2a/events SSE stream for v2 effects X-API-Key (read scope)
http://127.0.0.1:8000/manage Admin interface and agent workbench Tailscale IP, or loopback in local mode

3. Inspect The Hello World Example

The built-in agent is the v2 reference implementation:

Run the standalone example:

git clone https://github.com/supervaize/supervaize_hello_world.git
cd supervaize_hello_world
uv venv
source .venv/bin/activate
uv pip install -e .
supervaizer start

4. Add A V2 Controller To Your Agent

Run supervaizer scaffold to create supervaizer_control.py, or write the file yourself. It is a complete v2 agent: one registration, one surface, and one action. The scaffolded file also builds a Studio Account from the environment; local mode ignores it.

from typing import Any

from supervaizer import (
    Agent,
    Server,
    V2ActionRequest,
    V2SurfaceRequest,
    build_v2_agent_registration,
)

agent = Agent(
    name="My Agent",
    version="0.1.0",
    description="My Supervaizer v2 agent.",
    supervaizer_v2_registration=build_v2_agent_registration(
        agent_slug="my-agent",  # must equal Agent.slug, the slugified name
        display_name="My Agent",
        a2ui_catalog_version="my-agent-ui.1",  # bump when your surfaces change
        surfaces=["job.start"],
        actions=["job.start"],
    ),
)

server = Server(agents=[agent])


@server.v2_surface("job.start", agent_slug=agent.slug)
def job_start_form(request: V2SurfaceRequest) -> dict[str, Any]:
    return {
        "surface": request.surface,
        "document": {
            "type": "Form",
            "title": "Start job",
            "fields": [
                {"id": "goal", "label": "Goal", "type": "string", "required": True}
            ],
            "submit": {"action": "job.start", "label": "Start"},
        },
    }


@server.v2_action("job.start", agent_slug=agent.slug)
def start_job(request: V2ActionRequest) -> dict[str, Any]:
    job_id = request.job_id or "local-job"
    return {
        "status": "ok",
        "effects": [{"type": "job.started", "job_id": job_id, "status": "completed"}],
        "job_state": {
            "job": {
                "id": job_id,
                "mission_id": request.mission_id,
                "agent_slug": request.agent_slug,
                "status": "completed",
                "source": {"type": "fresh_start"},
            },
            "cases": [
                {
                    "id": "case-1",
                    "title": request.input["goal"],
                    "status": "completed",
                    "steps": [
                        {"id": "step-1", "activity": "operation", "status": "completed"}
                    ],
                }
            ],
        },
    }

Start it in local mode. The CLI loads supervaizer_control.py, finds the Server, and launches it:

supervaizer start --local

Load the surface:

curl -s http://127.0.0.1:8000/a2a \
  -H "X-API-Key: local-dev" -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "supervaizer/surface.load",
       "params": {"request_id": "r1", "actor": {"user_id": "me"},
                  "workspace": {"id": "local"}, "mission_id": "m1",
                  "agent_slug": "my-agent", "surface": "job.start"}}'
Part Role
build_v2_agent_registration Declares the surfaces Studio can show and the actions Studio can call.
@server.v2_surface Returns the A2UI document for one declared surface.
@server.v2_action Runs one declared action. Returns effects and an optional job_state snapshot.

Rules that prevent the usual first errors:

  • agent_slug in the registration must equal Agent.slug (the slugified name). A mismatch fails at Agent creation.
  • Register one handler for each declared action and each surface you serve. A missing action handler answers JSON-RPC error -32010; a missing surface handler answers -32011.
  • Pass agent_slug to each handler decorator. Local mode adds the built-in Hello World agent, so the server holds two agents and cannot infer the slug.
  • A bare action id defaults to mutating=True, scope="job". Declare a read-only action with V2ActionDefinition(id=..., mutating=False, scope=...).

Add these when you need them:

  • Status convergence: declare job_policy={"sync": {"action": "job.sync"}} and register a job.sync handler.
  • Human review: return a step with status="awaiting" and an awaiting object. Declare the case.step.awaiting surface and the step.awaiting.submit action.
  • Business objects: declare resources=[...]. The SDK derives the resource.<id>.<operation> actions; you register their handlers.

The built-in Hello World agent shows all three. Supervaizer v2 concepts holds the full model.

5. Connect To Studio

Studio-managed operation needs a supervisor_account on the Server, the controller's own API key, and workspace authorization trust material. The scaffold template (supervaizer scaffold) reads these variables:

export SUPERVAIZE_API_KEY=...            # agent -> Studio calls
export SUPERVAIZE_WORKSPACE_ID=...
export SUPERVAIZE_API_URL=https://app.supervaize.com
export SUPERVAIZER_API_KEY=...           # Studio -> controller calls (X-API-Key); generated if unset
export SUPERVAIZER_PUBLIC_URL=https://your-controller.example.com

# Workspace authorization: required when A2A is enabled and the controller registers with Studio
export SUPERVAIZER_WORKSPACE_AUTH_REQUIRED=true
export SUPERVAIZER_WORKSPACE_AUTH_ISSUER=https://studio.supervaize.com
export SUPERVAIZER_WORKSPACE_AUTH_JWKS_URL=https://app.supervaize.com/w/your-workspace-slug/api/v1/workspace-agent-grants/jwks/  # or SUPERVAIZER_WORKSPACE_AUTH_PUBLIC_KEY=<PEM>

Copy the generated workspace values from Studio's Developer → Environment variables section. SUPERVAIZE_WORKSPACE_ID must be the workspace slug shown there; the API key's user must belong to that workspace and retain Developer access. A mismatch can make SERVER_REGISTER return HTTP 403. The issuer must match Studio's token issuer. The JWKS URL is public and supplies the signing key. Workspace authorization is separate from SUPERVAIZE_API_KEY and SUPERVAIZER_API_KEY.

In your own control file, build the account explicitly; Server does not read the SUPERVAIZE_* variables itself:

import os

from supervaizer import Account, Server

account = Account(
    workspace_id=os.environ["SUPERVAIZE_WORKSPACE_ID"],
    api_key=os.environ["SUPERVAIZE_API_KEY"],
    api_url=os.environ.get("SUPERVAIZE_API_URL", "https://app.supervaize.com"),
)
server = Server(agents=[agent], supervisor_account=account)

Without the three SUPERVAIZER_WORKSPACE_AUTH_* variables, a Studio-registered controller refuses to launch (Studio-registered Supervaizer v2 A2A requires workspace authorization). Local mode does not need them. See docs/2026_05_WORKSPACE_AGENT_GRANTS.md.

Then start the controller:

supervaizer start

Studio registration remains the trust bootstrap. It owns server identity, public key exchange, and encrypted payload handling. The A2A Agent Card advertises the v2 operational contract after Studio knows the controller.

V2 Concepts

Concept Meaning
Job Committed work that Studio tracks for an agent.
Case A unit of work inside a Job, grouped by lane (default work).
Step An observable activity inside a Case: activity, status, optional awaiting, and outputs.
Surface A named UI entry point. Its handler returns an A2UI document.
Action A typed command invoked through A2A JSON-RPC. Its handler returns effects and an optional job_state.
Resource, Dataset Agent-owned business objects and queryable data that Studio renders generically.
Artifact An agent-owned output, referenced from Step outputs.

Failure is a status, not a step kind. Human review is status="awaiting" plus an awaiting object. Dynamic UI behavior is A2UI local logic or a typed action call, never a callback.

The full model, the standard surface and action ids, and the protocol split are in docs/2026_05_SUPERVAIZER_v2.md and docs/2026_05_PROTOCOLS.md.

CLI

Common commands:

supervaizer start
supervaizer start --local
supervaizer start --host 0.0.0.0 --port 8000

See docs/2025_08_CLI.md for the full CLI reference and environment variables.

Deployment

Install deployment extras:

pip install "supervaizer[deploy]"

Preview, smoke-test in Docker, and deploy:

supervaizer deploy plan --platform cloud-run --name my-agent --project-id my-gcp-project
supervaizer deploy local --name my-agent --generate-api-key
supervaizer deploy up --platform cloud-run --name my-agent --project-id my-gcp-project --region us-central1

Targets: Google Cloud Run, AWS App Runner, and DigitalOcean App Platform.

Experimental: deploy up builds the image locally but does not push it to a registry, and generated secrets are not injected under the variable names the server reads. Use plan and local today; finish cloud deployment with your provider's CLI.

See:

Admin Interface

The admin interface and agent workbench are mounted at /manage (admin_interface=True, the default). Access is restricted to Tailscale addresses (100.64.0.0/10), plus loopback in local mode; no API key is used. See docs/2025_08_ADMIN_README.md.

Development

Run tests and checks:

just test        # pytest, no coverage
just precommit   # ruff check, ruff format, mypy, hooks

Contributing

Supervaizer is public SDK infrastructure. Keep public contracts typed, generic, and free of agent-specific business logic. If a protocol field changes, update the producer and consumer documentation together.

Please see CONTRIBUTING.md for contribution details.

License

This project is licensed under the Mozilla Public License 2.0.

Metadata

Release files for supervaizer 1.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for supervaizer 1.7.0
File Size Uploaded
supervaizer-1.7.0.tar.gz 211.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for supervaizer 1.7.0
File Interpreter ABI Platform
supervaizer-1.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 490.5 kB

Release files / supervaizer-1.7.0.tar.gz

Download URL supervaizer-1.7.0.tar.gz
Size 211.7 kB
Tags Source
SHA-256 checksum
How to use checksums
fbe7baf9478e3da06e47c3e57e9266dc9e8638e5e03d1b3859b8f7d4b738cf1d
BLAKE2b-256 checksum
How to use checksums
16847c060c3dbb8f861d83ae3418b4bdc90253e28d82b5b74ae2d550ae531254
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / supervaizer-1.7.0-py3-none-any.whl

Download URL supervaizer-1.7.0-py3-none-any.whl
Size 278.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8bdc7df2c72995dd2ccd17a7bd83e8db013c2aaed35457922a3ba629a8dd59c
BLAKE2b-256 checksum
How to use checksums
417f4bd4087f3448be3102465996aebe4ad8a70ea71e9e99b3a84f6d7cc50aeb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

1.8.0

2 release files

This release

1.7.0 This release

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.20.1

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.1

2 release files

0.15.0

2 release files

0.14.2

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.3

2 release files

0.13.2

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.9

2 release files

0.10.8

2 release files

0.10.7

2 release files

0.10.6

2 release files

0.10.5

2 release files

0.10.4

2 release files

0.10.3

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.8

2 release files

0.9.7

2 release files

0.9.6

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page