Supervaizer Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
supervaizer login— Logs a developer in to Studio from the terminal with a device authorization: the command prints an approval page and a code, the developer signs in or signs up in the browser (Google included) and approves, and the command writes the threeSUPERVAIZE_*variables and the threeSUPERVAIZER_WORKSPACE_AUTH_*variables to an environment file (.envby default). It prints variable names only, never a value.supervaizer start --env-file <file>loads such a file before the control script. After a registration, the start log shows the Studio page of each agent when Studio sends it (studio_urlin the handshake agent entries). Needs a Studio with the/api/v1/cli/device/endpoints; an older Studio gets a clear error.- Integration skill in the SDK (PR #165) — The Supervaizer integration skill for coding agents moves from
runwaize/runwaize_skillstoskills/supervaizer-integration/and is released with the SDK. It interviews the developer about the mission, job, case and step mapping in rounds of questions, then builds the integration topic by topic (parameters, fields, shared resources, cost, human in the loop, guardrail controls, Configure screen, analytics). It holds the process only and points to the guides at docs.runwaize.com,supervaizer scaffold,docs/and the Hello World example for the contract, so it cannot drift from them..claude-plugin/marketplace.jsonlets Claude Code install it with/plugin marketplace add supervaize/supervaizer. The skill is not part of the wheel.docs/2026_05_SUPERVAIZER_v2.mdnow documents thejob.configuratorandjob.analyticssurfaces, theDashboarddocument and the job snapshot keys Studio reads. The skill also covers the Studio side (account, Developer access, API key, registration, workspace authorization, refused registrations), hosting and deployment, artifacts, scheduled start and the billing catalog. Its helper prints no environment value, fails on a JSON-RPC error, forwards the job, case, step and draft-session ids, sends no made-up job id, keeps an existing spec file unless--forceis given, and lists the cost task only when the spec has a cost. - Agent billable consumption (PR #155) —
Agent(billing_catalog=[...])andAgentRegistrationContract.billing_catalog(BillingCatalogItem:skuof 1 to 64 characters matching^[a-z0-9_]+$and unique in the list,unitof 1 to 32 characters,descriptionof at most 255) are sent only when set, so an agent without a catalog registers with the same keys as before.Account.report_consumption(records, *, agent_slug, workspace_id=None)andreport_consumption_syncpost aConsumptionReport(agent_slug, 1 to 200BillableConsumptionrecords) to/w/<workspace>/api/v1/billing/consumption/with theworkspaceheader set to the same workspace, and return oneConsumptionReceipt(accepted,duplicate, orrejectedwith areason) per record, in order, parsed throughConsumptionReportResponse.quantityandagent_cost_usdareDecimalvalues sent as strings;occurred_atmust be timezone-aware. Transport errors and whole-batch400/403are re-raised likesend_event; local mode accepts every record without HTTP.HELLO_WORLD_BILLING_CATALOGin the Hello World example shows a one-SKU catalog. Seedocs/2026_10_BILLABLE_CONSUMPTION.md. Requires a minor release.
Changed
- Production Python refactors (PR #163): Agent lifecycle, CLI startup, contracts, authentication, REST routes, deployment, and example jobs use smaller functions. Shared helpers replace repeated decisions. Characterization tests preserve existing payloads, errors, logs, and execution order. All scored production Python functions have CRAP below 10. The documentation generator remains exempt.
just ship-reconciletakes no arguments (PR #156) — The recipe only forwarded its own defaults, so the script's repo argument and--timeout-seconds/--poll-secondsparser are gone. Override with environment variables:TIMEOUT_SECONDS(default 1800),POLL_SECONDS(default 15), e.g.TIMEOUT_SECONDS=7200 just ship-reconcile. The script refuses any argument (exit 2), so a stale command cannot run against a repo it did not name; the repo is fixed tosupervaize/supervaizer. Tooling only, no package change.- Admin and workbench route factories split (PR #163) —
create_admin_routes(CRAP 1046) andcreate_workbench_routes(CRAP 1104) held every handler as a nested closure. Handlers are nowAdminHandlersmethods and module-level workbench functions, registered from route tables; the OpenAPI schema is unchanged. Shared helpers replace copied filter/sort/paginate, status-update, step-validation and error-to-500 code.set_server_start_time,SERVER_START_TIMEand theEntityFiltermodel were unused and are removed. Internal module only, no public API change.
Fixed
- Workbench job monitor returned 500 (PR #163) —
workbench_monitor.htmlusedx is not none if x is defined else false, which Jinja 3.1 parses as a test argument, soGET /manage/agents/<slug>/workbench/jobs/<job_id>raisedTemplateSyntaxErrorfor every existing job. The condition is nowx is defined and x is not none; a test compiles every admin template.
Tests
uv run just test-cov -p no:sugar -q
| Status | Count |
|---|---|
| ✅ Passed | 1559 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 127s |
| Metric | Before (5ad84c6) | After (97ea54f) |
|---|---|---|
| Tests | 1,003 | 1,559 |
src + tools coverage | 74.4% (9,415 statements, 2,413 missed) | 85.4% (9,475 statements, 1,380 missed) |
src only coverage | 82.0% (1,541 missed) | 94.1% (508 missed) |
tools only coverage | 0% (872 statements) | 0% (872 statements) |
[1.9.0] - 2026-10-29
Added
-
Agent full description (PR #151) —
Agent(full_description=...)andAgentRegistrationContract.full_description(V2AgentFullDescription:formatismarkdown(default) orhtml,contentis 1 to 100,000 characters and not whitespace only) are sent only when set, so an agent without one registers with the same keys as before. The SDK types and bounds the content; Studio sanitizes it before rendering it on the agent detail page. Requires a minor release. -
Guided setup contract (freeze of 2026-10-28) (PR #149) — Typed, optional additions for chat-guided job setup. An unmodified v2 agent registers byte-for-byte as before;
tests/test_registration_compat.pyholds the golden payloads.Agent(introduction=...)andAgentRegistrationContract.introduction(V2AgentIntroduction:tagline,summary,example_goals,avatar_url) are sent only when set.V2SetupFieldDefinitionwithV2FieldOption,V2FieldDependsOn(wire keyin),V2FieldValidationandlistfields withitem_fields;V2AwaitingFieldDefinitionandV2ResourceFieldDefinitiongain the same optional keys. Validators reject bare-stringoptions, rules that do not fit the field type,min_rowswithoutmultiline, and nestedlistitems.V2JobSetupPolicy.planandV2ActionResult.setup_planaccept aV2SetupPlan(confirmation_required,steps[]ofV2SetupStep,cost_estimate) or a dict that passes through untouched; a step'shelp_actionsmust be declared incapabilities.actionswithkind="help".V2ActionDefinition.kind(commandorhelp; help actions must bemutating=False),target_fieldanddry_run;V2ActionResult.draft(V2FieldDraft,V2Suggestion) andV2ActionResult.dry_run(V2DryRunOutcome).V2CostEstimateis anestimatedrange orunknown. Confirm idempotency rules are documented indocs/2026_05_SUPERVAIZER_v2.md, with the conformance helperassert_confirm_idempotent(handler, request)insupervaizer.testing. Requires a minor release.
Changed
- A2UI file fields and Studio-stored artifacts (PR #139) —
docs/2026_05_SUPERVAIZER_v2.mddocumentstype: "file"awaiting fields (accept,max_bytes,storage), the HITL answer shapes forstorage: "studio"andstorage: "inline", the inline request-body limit, and artifact refs that point at Studio-held bytes ("storage": "studio"+file_id). File fields are case awaiting steps only for now. just ship-reconcileopens a back-merge PR (PR #137) — The script pusheddevelopdirectly, which passed only through an admin bypass of thedevelopPR rule. It now mergesorigin/maininto achore/sync-main-<tag>branch cut fromorigin/develop, pushes that branch, and opens a PR todevelop; merge it with a merge commit. The--modeoption (and the recipe'smodeargument) is removed:rebaseneeded a non-fast-forward push todevelop, which the ruleset blocks..claude/ship.mdrecords the release flow for agents.- Dependencies —
uv.lock:opentelemetry-api1.45.1 (PR #150),virtualenv21.14.13 (PR #146),uv0.13.4 (PR #144),certifi2026.10.19 (PR #145),filelock4.2.1 (PR #147). GitHub Actions:astral-sh/setup-uv10.3.0 (PR #142),trufflesecurity/trufflehog3.99.3 (PR #138, #148),google/osv-scanner-actionreusable workflows 2.7.0 (PR #140, #143). No runtime change.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 930 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 44s |
[1.8.0] - 2026-10-11
Added
- Scheduled start capability (PR #132) — v2 agents opt in with
capabilities.scheduled_start: true; the default and explicitFalseomit the field. Registration rejects the opt-in unless the final actions declarejob.start. Studio owns the clock and invokes the existing action with a stable occurrenceidempotency_key. Seedocs/2026_10_SCHEDULED_START.md. - Product feature map (PR #131) —
docs/product/feature-map.mdindexes user workflows with routes, source, and pytest evidence.AGENTS.mdand the README point at it. Update the map when a workflow, route, or access rule changes. - Mission context on v2 requests and DataResource calls (PR #130) — New
V2MissionContext(id,name,metadata) carries StudioMission.metadatato the agent, uninterpreted.V2SurfaceRequest,V2ActionRequest,DataResourceContext, andDataResourceContextContractgain an optionalmission; a model validator requires a non-blankmission.idequal tomission_id, andmetadataaccepts a JSON object only. New headerX-Supervaize-Mission-Metadata(base64url UTF-8 JSON, 4096 bytes max) on DataResource proxy calls:build_data_resource_context_headers(..., mission_metadata=...)writes it,encode_mission_metadata_header/decode_mission_metadata_headerare exported, and the data routes setcontext.missionor return HTTP 400 on a bad header or a header without a non-blankX-Supervaize-Mission-Id. Optional and additive: requests withoutmissionbehave as before. Requires a minor release.
Changed
- Ruff 0.16 default lint rules (PR #133) —
pyproject.tomldrops theselect = ["E4", "E7", "E9", "F"]pin from PR #123 and lints with the Ruff 0.16 defaults. No-op findings are fixed: import order, quoted annotations, explicitsubprocess.run(check=False), stringos.getenvdefaults, and similar rewrites. Rules whose fix would change runtime behavior are ignored with a reason inpyproject.toml(BLE001, S110, DTZ005, TRY004, RUF012, UP040/UP046/UP047, plus per-file ignores); B008 accepts FastAPIBody,Depends, andQuerydefaults. No runtime change. A temporary B023 ignore inroutes.pymarked a known bug in v1 custom-method routes; PR #134 fixes it and removes the ignore. - Dependencies —
jaraco-context6.1.2 inuv.lock(devextra, via hatch and keyring; fixes PYSEC-2026-1469 / GHSA-58pv-8j8x-9vj2) (PR #135);astral-sh/setup-uv10.2.0 (PR #128);softprops/action-gh-release3.0.3 (PR #126);trufflesecurity/trufflehog3.97.9 (PR #129);google/osv-scanner-actionreusable workflows 2.6.0 (PR #125, #127).
Fixed
- v1 custom-method routes ran the last registered method (PR #134) —
POST /api/supervaizer/agents/{slug}/custom/{method}now callsservice_job_customwith its own method name, and the response message names that method. Before, every custom route ran the last method inagent.methods.custom. Route paths, operation names, and OpenAPI output do not change. TheB023ignore from PR #133 is removed. - README deploy section —
deploy upbuilds the image, pushes it to the platform registry, and stores generatedSUPERVAIZER_API_KEYandSUPERVAIZER_PRIVATE_KEYas platform secrets. The previous "experimental, does not push" note described an older command. - Workbench is v1-only —
POST /manage/agents/{slug}/workbench/startreturns HTTP 400 for an agent with no v1methodsand does not create a job. v2-only agents run throughPOST /a2a. - Data-resource routes were undocumented — CRUD lives at
/api/agents/{slug}/data/{name}/, requiresX-API-Keyplus a workspace token, and is not covered by the local-mode/a2abypass. - Local-mode host and workspace-auth docs — Wildcard hosts (
0.0.0.0,::, empty) bind127.0.0.1; an explicit--hostis kept. The/a2abypass ignores leeway andSUPERVAIZER_WORKSPACE_AUTH_REQUIRED=false.POST /a2ais mounted by default; only/apiwaits for a Studio account or local mode. JSON-RPC-32030useserror.data.codeworkspace_authorization_missingorworkspace_authorization_not_configured.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 851 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 48s |
[1.7.0] - 2026-10-04
Added
- Local mode can invoke v2 actions and surfaces (PR #117) — With
SUPERVAIZER_LOCAL_MODE=true, nosupervisor_account, and noSUPERVAIZER_WORKSPACE_AUTH_*trust setting,POST /a2asupervaizer/action.invokeandsupervaizer/surface.loadno longer answer-32030 workspace_authorization_not_configured. Handlers get an unverified workspace context withgrant_id="local-mode"(LOCAL_MODE_WORKSPACE_GRANT_ID) and only the scopes the call needs, and startup logs a bypass warning. Any trust setting (even withoutSUPERVAIZER_WORKSPACE_AUTH_REQUIRED=true) or an attached Studio account keeps the fail-closed check, and data-resource routes never bypass. - Rule checkpoint gates (PR #113) — V2 controllers can explicitly declare
beforeandafterrule-checkpoint support, including declared business-secret paths.RuleCheckpointGateandCase.run_guarded_step()request Studio authorization around a cooperative effect, persist the outcome for safe recovery, and receive approved pauses through the declaredrule.checkpoint.resumeaction. - Optional label and description on surfaces and actions (PR #103) — Additive v2 registration contract:
V2SurfaceDefinition(id, label, description),V2AgentCapabilities.surface_definitions, and optionallabel/descriptiononV2ActionDefinition. Display text is trimmed and capped at 300 characters; blank counts as absent. Existing agents that omit the fields keep byte-identical cards (capabilities.surfacesstays a list of ids).
Changed
- Shorter v2 on-ramp (PR #121) —
build_v2_agent_registrationneeds onlyagent_slug,display_name, anda2ui_catalog_version.agent_iddefaults to the slug,controller_urlto/a2a, andagent_card_urlto/.well-known/agents/<slug>_agent.json(the unversioned card route); explicit values keep their behavior.supervaizer scaffoldgenerates a minimal Supervaizer v2 controller (one registration, onejob.startsurface, onejob.startaction) instead of the v1AgentMethodtemplate.docs/api/openapi.jsonis regenerated from it, so the v1 job routes of the old example leave the published reference; the SDK still serves them for v1 agents. The README quick start is a single short v2 agent. - v1 methods are optional for v2 agents (PR #114) —
Server(agents=[agent])no longer raisesAgent <name> has no methods definedwhen the/apirouter is mounted (Studio account orSUPERVAIZER_LOCAL_MODE=true) and the agent declares onlysupervaizer_v2_registration. Such agents keep the agent-level routes (info, instructions, parameter validation,/parameters) but get no v1 job routes (/jobs,/stop,/status); Studio runs their jobs through/a2a. The registration payload is unchanged (methods: {}). An agent with neithermethodsnor a v2 registration still raises. The README v2 sample drops its placeholderjob_startmethod. - Documentation audit (PR #104) — README, AGENTS.md, CONTRIBUTING.md, SECURITY.md, and
docs/verified against the 1.6.0 code. Fixed: admin UI path and access model (/manage, Tailscale-gated,ADMIN_ALLOWED_IPSremoved), the README v2 sample (mission_id, explicitV2ActionDefinition), Studio connection (Accountwiring and theSUPERVAIZER_WORKSPACE_AUTH_*launch requirement), CLI reference (actualdeployoptions, non-functional--reload/--debug), persistence (the singleton ignoresdb_path; noCachingMiddleware), workspace authorization (WorkspaceAuthorizationClaims, exact bootstrap ids, env vars), CONTRIBUTING (mypy path, 88 columns, gitmoji commits, PRs targetdevelop), and SECURITY (supported versions, actual branch rulesets).docs/2025_08_ADMIN_README.mdanddocs/2025_08_REST_API.mdrewritten;docs/2025_10_LOCAL_TESTING.mdmarked legacy; RFC statuses updated;GEMINI.mdand.cursorrulesnow point toAGENTS.md. - Deploy credentials stay out of the image (PR #111) — The generated Dockerfile no longer bakes
SUPERVAIZE_API_KEYand the other host variables in asARG/ENV;uppasses them at runtime and storesSUPERVAIZE_API_KEYin the platform secret manager.docker-compose.ymland the DigitalOcean app spec are written with mode600, anddeploy localpublishes its port on127.0.0.1only. deploy up --imagetakesname[:tag](PR #111) —upadds the platform registry and rejects a value that contains/.- DigitalOcean uses the account container registry (PR #111) —
upno longer creates a{name}-{env}registry anddownno longer deletes it; DigitalOcean allows one registry per account. - Deployment drivers declare their registry (PR #111) —
BaseDrivergainsprepare_registry()and an overridableregistry_auth().prepare_registry()is not abstract, so existing third-party driver subclasses still instantiate;deploy upraisesNotImplementedErrorfor a driver that does not implement it. - Agent Card points at real routes (PR #115) —
api_endpoints[].urland its examples now use/api/supervaizer/agents/{slug}, andhuman_urlpoints at the agent's instructions page, which needsX-API-Keylike every/api/*route.authenticationdeclares theX-API-Keyheader instead ofnone. Behavior change for card consumers:authentication.typeis nowapiKey;version_info.latest(always equal tocurrent), the dead/changelog/{slug}URL, andlogo_url(no route served it) are removed;version_info.changelog_urlappears only when the agent setsrelease_notes_url. Studio reads only the card'ssupervaizer.v2extension, so it is not affected. - Dependencies — anyio 4.14.2 (PR #102); httpcore2 2.10.0 (PR #100); httpx2 2.12.0 (PR #101); urllib3 2.8.0 (PR #105); virtualenv 21.7.13 (PR #106);
actions/checkout7.0.1 (PR #97);astral-sh/setup-uv10.0.1 (PR #96);trufflesecurity/trufflehog3.97.1 (PR #98);google/osv-scanner-actionreusable workflows 2.5.1 (PR #95, #99). Minimum versions raised (PR #122):deployextra boto3 1.43.108, docker 7.2.0, google-cloud-artifact-registry 1.23.0, google-cloud-run 0.16.2, google-cloud-secret-manager 2.31.0;devextra hatch 1.18.1, mypy 2.4.0, pre-commit 4.6.2, pytest-mock 3.16.0, ruff 0.16.10.
Deprecated
supervaizer start --debugand--reload(PR #111) — Both options still run but are hidden from--helpand print a deprecation warning.--debugstill setsSUPERVAIZER_DEBUGand turns on FastAPI debug mode in the no-script--localfallback;Serveritself never reads the variable.--reloadstill setsSUPERVAIZER_RELOAD, but the fallback no longer passes it to uvicorn, where it crashed (You must pass the application as an import string). For debug mode, setdebug=Trueon theServerin a control script. Restart after code changes.
Removed
- Stale docs and TODO block (PR #104) —
docs/2025_04_API_REFERENCE.md(v1 examples that no longer run),docs/2025_08_PROTOCOLS.md(subset of2026_05_PROTOCOLS.md),docs/superpowers/plans (shipped or removed features), and the CHANGELOGTODOblock.docs/2025_08_PARAMETER_VALIDATION_IMPLEMENTATION.mdtrimmed todocs/2025_08_PARAMETER_VALIDATION.md. - Dead admin allowlist and
Server.verify_api_key(PR #112) — Deletesadmin/ip_allowlist.py(ADMIN_ALLOWED_IPS, unused since 0.15.0),Server.verify_api_key/Server.api_key_header(API-key checks live on the router), andtools/test_admin.py. - Root-level smoke scripts (PR #111) —
test_local.py(it ranpython -m supervaizer, which has no__main__; usesupervaizer deploy local) andtest_dockerfile_generation.py(license header only). - No-op deploy flags (PR #111) —
deploy up --yes,deploy up --no-rollback, and--verboseondeploy plan,up,down, andstatusdid nothing. They now fail as unknown options.deploy down --yesand--verboseondeploy localandcleanremain.
Fixed
/managepages no longer expose the API key (PR #116) — Every admin page put the write-scopeSUPERVAIZER_API_KEYin adata-admin-keyattribute on<body>, and the workbench page also inlined it in its script. Anyone who could open/managecould read the key and call the write-scope/api/*routes with it. Since 0.15.0,require_tailscalegates/manageand its endpoints need no key, so the templates andworkbench-form.jsno longer receive or send it. The/manage/job-start-testpage andjob-start-form.jsare removed: the page never loaded the script, and the script targeted an agent path that does not exist.- Job responses and storage no longer hold decrypted parameters (PR #118) —
POST /api/supervaizer/agents/{slug}/jobsreturned the decryptedagent_parameterslist, secret values included, andJob.to_dictwrote it to the job store.AbstractJob.agent_parametersis now excluded from serialization andrepr; the agent method still gets the values at run time.service_job_custompasses its decrypted list to that run only (newAgent.job_startagent_parametersargument), because a job reloaded from storage no longer has it, and thejob_startand_executedebug logs no longer print it. Job records saved before this release keep their parameters, because the store merges updates: after you upgrade, removeagent_parametersfrom theJobrecords in$DATA_STORAGE_PATH/entities.json(default./data/entities.json). Behavior change:Job.to_dict, the job start response, and the OpenAPIJobschema no longer includeagent_parameters. - Valid empty registration parameter setup (PR #109) — Agents without parameter definitions now send an empty list instead of
null. - Safer HTTP error diagnostics (PR #107, #108) — Diagnostic curl output masks authorization and API-key headers, serialized event details redact API keys and token fields, and HTTP errors log the remote status and request ID.
just devstarts the controller (PR #111) — The recipe ranuvicorn controller:app --reload, but there is nocontrollermodule.just devis now an alias ofjust local(uv run supervaizer start --local).- Correct refresh hint (PR #111) — When
supervaize_instructions.htmlalready exists, the CLI now points tosupervaizer scaffold refresh-instructionsinstead of the nonexistentsupervaizer refresh-instructions. - Git hooks run the pre-commit checks (PR #111) —
just install-hooksinstalled the.pre-commit-config.yamlhooks in.git/hooksand then setcore.hooksPath=.githooks, so Git ignored them, and.githooks/pre-commitonly called apre-commit-userscript that did not exist..githooks/pre-commitnow runs the pre-commit stage (Ruff, mypy, license header) on the staged files and still refuses a plaingit commitongitbutler/workspace; the new.githooks/commit-msgruns the gitmoji and commitizen checks..githooks/post-commitreadssrc/supervaizer/__version__.py, so a version-bump commit is taggedvX.Y.Zinstead ofv.just install-hooksonly setscore.hooksPath. Removed the GitButler-managed.githooks/post-checkout, which deleted itself from the tree on each checkout away fromgitbutler/workspace.just shippasses--no-verifyto its release merge, because the commit-msg hook rejects the[MINOR]title. GitButler'sbut commitdoes not run Git hooks. - Post-commit hook tags release versions only (PR #119) — A plain
git commitofjust version-dev oncreated a localvX.Y.Z.dev0tag, andjust version-dev offfailed withtag 'vX.Y.Z' already existsbut still printedCreated tag. The hook now callsjust tag-version, which tags onlyX.Y.Zversions, skips an existing tag, and printsCreated tagonly whengit tagsucceeds. deploy uppushes the image it deploys (PR #111) —upnow pushes the built image to the platform registry (Artifact Registry, ECR, or the account DigitalOcean registry, with short-lived credentials) and deploys that reference. Before, Cloud Run and App Runner pointed at an image that was never pushed, and DigitalOcean used a placeholder GitHub source. Cloud Run now deploys withallow_missingand waits for the operation; App Runner gets a string map inRuntimeEnvironmentVariablesand secret ARNs inRuntimeEnvironmentSecrets; DigitalOceanSECRETenvs carry their value.- Deployed containers get the variables the server reads (PR #111) — Generated secrets arrive as
SUPERVAIZER_API_KEYandSUPERVAIZER_PRIVATE_KEY(was{name}-{env}-api-key,{name}-{env}-rsa-key, andSV_RSA_PRIVATE_KEY), and the log level asSUPERVAIZER_LOG_LEVEL(wasSV_LOG_LEVEL).SUPERVAIZER_SERVER_IDand theSUPERVAIZER_WORKSPACE_AUTH_*variables are forwarded, so a Studio-registered v2 controller starts in the container.--portnow setsSUPERVAIZER_PORTas well as the container port. deploy localhealth check and Compose (PR #111) — The health check probes/.well-known/health(the/agents/healthroute no longer exists), commands use Docker Compose v2 (docker compose), the hostSUPERVAIZE_API_KEYis no longer replaced by the controller test key, and multi-line values such as PEM keys are quoted indocker-compose.yml.- Launch stops when the Studio agent lookup fails (PR #120) —
Agent.update_agent_from_serverused to log a failedGET /agents/{id}or/agents/by-slug/{slug}and returnNone, soServer.launchkept going without the agent's Studio status or parameters. It now raisesRuntimeErrornaming the slug,server_agent_id, URL, and HTTP status. A 404 from Studio hid anAgent ID mismatchthis way. Behavior change: a Studio-registered controller no longer starts while Studio cannot return its agent. Local mode (no Studio account) still returnsNone. - Parameter validation accepts the job-start payload (PR #115) —
POST /api/supervaizer/agents/{slug}/validate-agent-parametersturned the decrypted list of{name, value}objects that Studio sends intoparam_0,param_1, ... keys, which then failed as unknown. Job start (Job.new) only accepts that list, so an agent with required parameters had no payload that passed both. The route now reads the list byname, so one encrypted payload passes both. The{NAME: value}dict form stays accepted for validation only; job start still requires the list. A list item without a stringnameand avalue, or a payload of another type, now fails with a clear error instead of being validated as empty. - Deploy home-page template links (PR #115) —
deploy/templates/index.htmllinked to/adminand/console; it now links to/manageand/manage/console. - Rule checkpoint recovery (PR #113) — Early resume delivery wakes live waiters, resumed proposals retain step identity, and lost after responses retry only evaluation. Concurrent original execution and recovery cannot advance a step twice.
- Ruff rule set is explicit (PR #123) — Ruff 0.16 enlarged its default rule set, and the
pre-commitcheck failed with 266 findings.[tool.ruff.lint] select = ["E4", "E7", "E9", "F"]keeps the rules that ran before. Ruff 0.16 also formats Python code blocks in Markdown, so three docs files are reformatted.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 808 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 43s |
[1.6.0] - 2026-08-30
Added
-
Declared action scope and mutability (#92) —
V2AgentCapabilities.actionsis nowlist[V2ActionDefinition]instead of an opaquelist[str]. Each action declaresid,mutating(does invoking it change agent-side state?), andscope(workspace/mission/job), so a consumer can authorize and group actions without pattern-matching the identifier.idis caller-supplied at invocation time, so deriving an authorization decision from it puts that decision in the caller's hands.Plain strings are still accepted everywhere a list of actions is taken — in
build_v2_agent_registration(actions=...)and when validating a registration payload — and coerce tomutating=True, scope="job", the fail-closed reading that matches today's behaviour. Only the serialized form changes:capabilities.actionsnow emits objects. Consumers must accept both, because agents pinned to older Supervaizer releases keep sending bare strings. No protocol version discriminates the two shapes:versions.a2ui_versionandversions.a2a_versioncover the surface catalog and the A2A protocol, not the registration payload.The builder derives the metadata from the definition each action comes from: resource actions take
V2ResourceDefinition.scope, dataset queries aremutating=False,V2JobSetupPolicy.preview_actionismutating=False, and workspace binding actions areworkspace-scoped. Resource operation ids are freeform, so operations staymutating=Trueunless the agent declares otherwise.Metadata precedence is explicit > derived > bare: an explicit
V2ActionDefinitioninactions=overrides the derived metadata — that is how a job-scopedresource.invoice.reconcileon a workspace-scoped resource is declared — while a bare id string declares nothing and defers to the definition it was derived from. Precedence is about metadata, not position: an id declared both ways withinactions=keeps the explicit metadata regardless of which form comes first, and the earlier mention still fixes the order. -
V2DatasetDefinition.scope— MirrorsV2ResourceDefinition.scope(workspace/mission/job, defaulting toworkspace) so dataset query actions carry a declared scope rather than an assumed one. -
V2AwaitingState.reopenable— Declares whether an already-answered awaiting step may be reopened and resubmitted with edited values. Defaults toFalse; previously consumers inferred this from a substring ofsurface.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 698 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 67s |
[1.5.0] - 2026-08-28
Added
-
Generic job setup contract — New
V2JobSetupPolicyonV2JobPolicy.setuplets an agent declare the actions Studio may use to preview, start, and submit a job setup (preview_action,start_action,submit_action, defaulting tojob.start.preview,job.start, andstep.awaiting.submit), the contexts those actions apply to (action_scopes), and an opaqueplanpayload. Declared actions are folded into the registration's capability action list.V2ActionResult.setup_plancarries the agent's plan back to Studio.V2JobSetupPolicyis exported at package level. Additive only; agents that omitsetupare unaffected.action_scopesdefaults to an empty list: an agent that opts in withsetup: {}declares no scopes rather than claiming all ofworkspace,job,case, andstep. This matchesV2JobSyncPolicy.supported_statusesand avoids advertising context support the agent never configured. The three action ids are validated as non-blank, so a blank id is rejected at registration instead of being silently dropped fromcapabilities.actionswhile still appearing in the serializedjob_policy.setup. The same validation was applied toV2JobSyncPolicy.action, which had the identical gap.
Changed
- Regenerated model reference and OpenAPI —
docs/model_reference/anddocs/api/openapi.jsonwere rebuilt from the current models, picking up the job setup contract along with accumulated drift since0.20.1.V2JobSetupPolicyis now declared beforeV2JobPolicyso the public reference renders the real type instead of aForwardRef.
Fixed
- PyPI publish (Metadata 2.5) — Pin
pypa/gh-action-pypi-publishto v1.14.2 so hatchling ≥1.32 wheels upload. Skip version bump unless the triggering commit has[MAJOR]/[MINOR]/[PATCH].
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 691 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 65s |
[1.4.0] - 2026-07-07
Added
- Security & performance review summary — Added
docs/2026_07_SECURITY_REVIEW.md, a non-actionable high-level summary of a full-source security and performance/scalability review (posture, verified-sound controls, severity counts, and remediation themes). PerSECURITY.md, detailed findings (locations, attack scenarios, remediation specifics) are handled through the private vulnerability channel and are intentionally omitted from the public repository.
Fixed
- Hardened API-key checks — API keys are compared in constant time.
- Safer local test mode —
supervaizer start --localbinds to loopback (127.0.0.1) by default instead of all interfaces; pass an explicit--hostto override. - Baseline security response headers — Responses now set
X-Content-Type-Options,X-Frame-Options,Referrer-Policy, andStrict-Transport-Security(streaming/SSE-safe). - Reduced sensitive data in logs — Agent parameter values are no longer written to logs during parameter validation.
- Scheduled-step execution hardening — The scheduler only runs methods declared by the agent that owns the step's job.
Tests
| Status | Count |
|---|---|
| ✅ Passed | 683 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 83s |
[1.3.1] - 2026-07-02
Changed
pyproject.toml(since v1.3.0) — Runtime lower bounds: FastAPI>=0.139.0, sse-starlette>=3.4.5, Typer>=0.26.8, Uvicorn>=0.49.0.deployextra: boto3>=1.43.39, google-cloud-run>=0.16.1, google-cloud-secret-manager>=2.23.0.devextra: hatch>=1.17.0, pytest>=9.1.1, pytest-asyncio>=1.4.0, ruff>=0.15.20. Lock file refreshed viauv lock.
Fixed
- A2A event scope test —
tests/test_a2a.pynow walks FastAPI included-router wrappers when locating/a2a/events, preserving the read-scope assertion under FastAPI0.139.0.
Tests
| Status | Count |
|---|---|
| ✅ Passed | 683 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 56s |
[1.3.0] - 2026-07-02
Added
context.assigncontract — New typed wire contract for assigning a frozen Studio context selection to a job:V2ContextAssignment(items,mission_id,job_id,assigned_at),V2ContextAssignmentItem(ref,version,scope,title), and theV2_ACTION_CONTEXT_ASSIGNaction id insupervaizer.contracts, exported at package level. Additive only; dispatch uses the existing genericServer.v2_actionmachinery.
Tests
tests/test_common.py— structured JSON log output for API access-denial recordsjust test
| Status | Count |
|---|---|
| ✅ Passed | 677 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 65s |
[1.2.0] - 2026-05-27
Changed
- FastAPI lifespan cleanup — Controller shutdown now cancels the scheduled-step background loop and waits briefly for it to stop.
- Server module refactor — Split server startup configuration, runtime server info persistence, Studio registration handshakes, and scheduled-step loop management out of
server.pyinto focused modules while preserving the publicServerbehavior. - Supervaizer v2 agent methods — SDK agents can now declare optional standard actions such as
agent.refreshplus custom agent actions through the sameAgentMethodsstructure used for job methods, and the A2A runtime registers those handlers automatically.
Tests
tests/test_server.py— scheduler task cancellation and bounded shutdown waiting during FastAPI lifespan shutdown.tests/test_server_refactor_modules.py— parity coverage for the extracted server configuration, server info, registration, handshake, and scheduled-step helpers.tests/test_a2a.py— standard and custom agent method dispatch through the v2 A2A controller.tests/test_agent.py— agent-level v2 method registration and contract validation.tests/test_contracts.py— typed agent method contract serialization.
Tests
tests/test_common.py— structured JSON log output for API access-denial recordsjust test
| Status | Count |
|---|---|
| ✅ Passed | 672 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 86s |
[1.1.1] - 2026-05-20
Changed
- Cloud Logging structured output —
SUPERVAIZER_LOG_FORMAT=jsonnow switches controller stderr logs to newline-delimited JSON with Cloud Logging-compatibleseverityplus bound fields such as access-denialpath,reason, and truncatedkey_preview; local text logging remains the default.
Tests
tests/test_common.py— structured JSON log output for API access-denial recordsjust test
| Status | Count |
|---|---|
| ✅ Passed | 658 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 92s |
[1.1.0] - 2026-05-19
Added
- Workspace agent authorization — Studio-signed Ed25519 workspace authorization tokens on
X-Supervaize-Workspace-Authorization; the SDK verifies JWKS-backed tokens and exposesV2VerifiedWorkspaceContextfor handlers. Workspace and tenant slugs remain routing hints only. - Workspace binding rotocol — Agents can declare optional
workspace_bindingmetadata with bootstrapworkspace_binding.options,workspace_binding.create, and theworkspace_binding.createsurface so Studio can bind an agent-side record before a Workspace Agent Grant exists. - Workspace authorization docs —
docs/2026_05_WORKSPACE_AGENT_GRANTS.mdplus workspace authorization and binding bootstrap rules indocs/2026_05_PROTOCOLS.mdanddocs/2026_05_SUPERVAIZER_v2.md.
Changed
- Fail-closed Studio A2A — Workspace-scoped v2 JSON-RPC actions and surfaces reject requests without a valid workspace authorization token when workspace authorization is enabled.
- Workspace-scoped data resources — Data resource routes require verified workspace context from the authorization token instead of trusting caller-supplied slugs alone.
- Studio server audience handoff —
server.registerhandshakes can now supply the Studio-persisted server audience for workspace authorization tokens, and Supervaizer adopts that audience before serving protected v2 calls so workspace grants survive agent process restarts. - Controller version registration —
server.registernow sends the Supervaizer controller package version directly ascontroller_version, so Studio no longer depends on OpenAPI scraping to refresh the server detail page version.
Fixed
- Workspace authorization validation — Malformed or incomplete workspace authorization tokens and settings now fail with explicit
workspace_authorization_*errors instead of ambiguous handler failures.
Tests
tests/test_a2a.py— workspace authorization accept/reject paths, JWKS verification, binding bootstrap exceptions, and protected action/surface enforcement.tests/test_agent.py— v2 registration carries workspace binding and authorization settings.tests/test_contracts.py— workspace binding and authorization contract models.tests/test_routes.py— data resource routes require verified workspace context.tests/test_server.py— registration handshake audience handoff, workspace authorization startup validation, andcontroller_versionregistration.
just test
| Status | Count |
|---|---|
| ✅ Passed | 657 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 76s |
[1.0.1] - 2026-05-17
Supervaizer v2 2️⃣
- Supervaizer v2 case metadata —
V2CaseSnapshotnow carries optional publicmetadataso agents can expose case-level business context such as contact interview links without adding agent-specific fields to the protocol. - Studio registration handshake validation — After
server.register, startup validatessupervaizer_handshake.controller_api_key_matchand fails when Studio persisted a different controller API key than the one this process is using (configuredSUPERVAIZER_API_KEYor auto-generated key). - Controller API key reload stability — Auto-generated controller keys are written to
SUPERVAIZER_API_KEYbefore registration so Uvicorn reload keeps the same key; startup logs a short SHA-256 fingerprint instead of printing the full secret.
Tests
tests/test_contracts.py—V2CaseSnapshotaccepts publicmetadata.tests/test_server.py— registration handshake accept/reject paths and generated API key export for reload.
just test
| Status | Count |
|---|---|
| ✅ Passed | 645 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 77s |
[1.0.0] - 2026-05-17
Supervaizer v2 2️⃣
- Supervaizer v2 documentation — Added
docs/2026_05_SUPERVAIZER_v2.mdand updated the README/protocol docs to explain the v2 A2A/A2UI layering, registration model, resources, datasets, surfaces, actions, HITL, artifacts, andjob.syncconvergence semantics. - Supervaizer v2 README — Reworked the repository README as a v2-first onboarding guide, linking to the protocol docs and Hello World example while removing the old v1 scaffold/job-field quick start path.
- Supervaizer v2 contract primitives — Added typed SDK models for the v2 registration and action contract, including pinned A2UI/A2A versions, resources, datasets, case lanes, artifact declarations, job snapshots, sync metadata, and replay-safety metadata.
- A2A JSON-RPC action runtime — Added the
/a2asupervaizer/action.invokedispatcher, v2 Agent Card extension payloads, and public SDK helpers for registering typed v2 actions throughServer.register_v2_action()and@server.v2_action(...). - A2A SSE event stream — Added
/a2a/eventsand an in-process v2 event bus so action effects returned throughsupervaizer/action.invokecan also be observed over Server-Sent Events. - Supervaizer v2 transport honesty —
V2A2ATransport.push_notificationsnow defaults tofalse; the MVP advertises JSON-RPC and SSE support only until A2A push notifications are implemented. - A2A JSON-RPC surface runtime — Added
supervaizer/surface.load, typedV2SurfaceRequest/V2SurfaceResultmodels, and public SDK helpers for registering A2UI surface handlers throughServer.register_v2_surface()and@server.v2_surface(...). - Supervaizer v2 agent identity guard —
Agentnow rejects v2 registration payloads whose declaredagent.slugdiffers from the runtime SDK slug, preventing A2A action handlers from registering under one slug while Studio invokes another. - Supervaizer v2 job sync state —
V2JobSyncResultnow carries an optionaljob_statesnapshot so agents can return convergent Job/Case/Step/Artifact state throughjob.sync. - Supervaizer v2 job source target metadata —
V2JobSourcenow includes an optionaltarget_typeso external sources can declare the business object Studio should use for dedupe and catch-up. - Supervaizer v2 resource form fields —
V2ResourceDefinitionnow carries typedfieldsmetadata so Studio can render simple agent-owned resource create/edit forms without callback-style dynamic field logic. - Supervaizer v2 ResourceImport documents — Added a typed A2UI
ResourceImportdocument contract so agents can declare import formats, contextual fields, row columns, and submit actions without adding agent-specific protocol fields. - Supervaizer v2 resource option sources — Resource fields can now declare typed resource-backed
options_sourcemetadata so Studio can render relationship selectors without callback-style dynamic choices. - Supervaizer v2 workspace-scoped resources — Resource declarations now advertise
scopeandrequires_contextmetadata, and legacy DataResource registration info carries the same workspace context requirement for Studio-side access control. - Supervaizer v2 dataset display metadata —
V2DatasetDefinitionnow carries typed display columns so Studio can render generic dataset surfaces from the registration contract. - Supervaizer v2 dashboard widgets — Added generic dashboard and widget registration contracts, including dataset/action/inline data refs and Vega-Lite widget specs under
visualization: { type: "vega-lite", spec: ... }without AnalyticsResource REST routes. - Supervaizer v2 mounted HITL review docs — Documented
DocumentReviewas a generic A2UI document payload for mounted awaiting-step surfaces without adding agent-specific protocol fields. - Supervaizer v2 registration builder — Added
build_v2_agent_registration()to derive validated v2 registration payloads from public SDK primitives, including generated resource/dataset surfaces and actions. - Supervaizer v2 public SDK ergonomics — Exported the remaining v2 registration helper models from
supervaizerand neutralized agent-specific examples in v2 public documentation and contract descriptions. - Legacy dynamic choices removed — Removed the v1
dynamic_choicesfield metadata,dynamic_choices_callback,/start/dynamic_choicesroute, and related contract exports; dynamic options now belong to v2 resourceoptions_sourcemetadata or typed A2A actions. - Legacy job poll removed — Removed
job_pollfrom the public v1 method contract and the local workbench poll route/button; v2 status convergence is represented by the typedjob.syncaction. - Supervaizer v2 awaiting form fields — Step awaiting state can now declare typed form fields so Studio can submit HITL actions through
step.awaiting.submit. - Local Hello World v2 contract — The built-in local Hello World agent now declares a minimal Supervaizer v2 registration through the SDK builder and registers
job.start,job.sync,case.step.awaiting, and a generated resource handler for local Studio and SDK smoke tests. - Controller correctness fixes — Scoped
Jobs.get_job(..., agent_name=...)to the requested agent, gaveEventType.AGENT_SEND_ANOMALYa distinct value, and fixed custom method routes to parse normal JSON request bodies. - Supervaizer v2 runtime hardening — Added typed common fields to v2 action effects, including resource import counts, rows, errors, gaps, summaries, and case snapshots; validated
job_stateon action results; authenticated the A2A JSON-RPC controller and SSE event stream while keeping A2A discovery/health public; sanitized A2A handler errors; and constrained legacy method execution to declared non-blocked method paths. - Supervaizer v2 replay and context contracts — Action results now validate and serialize replay-safety metadata, and DataResource context header generation includes the agent slug advertised by the contract model.
Tests
uv run pytest tests/test_a2a.py tests/test_contracts.py -q
just test
| Status | Count |
|---|---|
| ✅ Passed | 601 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 69s |
[0.20.1] - 2026-05-13
Security
uv.lock— Refreshed transitive versions to address open Dependabot / GHSA advisories on the default branch graph: urllib3 (redirect and decompression-chain issues), requests (extract_zipped_pathstemp reuse), protobuf (JSON recursion depth), pyasn1 (decoder / recursion DoS), pygments (ReDoS in GUID lexer), and uv (ZIP / tar / RECORD handling; dev dependency via hatch).
[0.20.0] - 2026-05-13
Security
- Secret scanning + push protection — enabled on the repository; credentials pushed by mistake are now blocked at the source.
- Dependabot alerts + automated security updates — enabled; known-CVE dependency updates are now proposed automatically.
- Private vulnerability reporting — enabled; researchers can report issues privately via GitHub Security Advisories instead of public issues.
- Branch ruleset on
main— replaces classic branch protection; requires all CI checks (pre-commit,build 3.10–3.13) to pass before merge, enforced on admins. Classic protection had no required checks and did not enforce on admins. - Tag ruleset —
v*release tags are now immutable; they cannot be moved or deleted. pypienvironment protection — required reviewer approval added; a push tomainno longer publishes to PyPI without a human gate.- SHA-pinned GitHub Actions — all third-party actions pinned to commit SHAs (
trufflehog,setup-uv,gh-action-pypi-publish,action-gh-release). Previouslytrufflesecurity/trufflehog@mainwas a floating branch reference — a critical supply-chain risk. uv sync --frozen— enforced in CI; the lockfile can no longer silently change during a build.- OSV-Scanner (
google/osv-scanner-action) — added as a daily scheduled scan and on every PR targetingmainordevelop, against the OSV.dev malicious package index. - Dependabot configuration (
.github/dependabot.yml) — weekly updates forpipandgithub-actionsecosystems with a 5-day cooldown window to mitigate supply-chain worm attacks; all PRs routed todevelop. SECURITY.md— added; documents the responsible disclosure process (GitHub private advisories) and the repository's supply-chain posture.AGENTS.mdsecurity rules — mandatory rules added for coding agents: no direct pushes tomain, no manual lockfile edits, no workflow modifications without approval, no localhatch publish.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 570 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 69s |
[0.19.0] - 2026-05-11
Added
- Agent method timeout metadata —
AgentMethodand the registration contract now exposeis_asyncandtimeoutmetadata for Studio.timeoutdefaults to 600 seconds and can benullfor controller jobs that should run until Studio stops them manually.
Changed
pyproject.toml(since v0.18.0) — Runtime lower bounds: FastAPI, orjson, packaging, Pydantic, python-slugify, Rich, sse-starlette, TinyDB, Typer, Uvicorn.deployextra: boto3 and Google Cloud libraries (Artifact Registry, Cloud Run, Secret Manager).devextra: addboto3,docker, andblacksouv sync --extra devmatches deploy/docker-heavy tests and Black in CI; addyamllint; bump mypy, pre-commit, pytest, respx, ruff.[tool.black]: explicit Black config (line length 88, Python 3.12–3.13 targets, excludes for caches/venv/dist).
Tests
uv run pytest tests/test_agent.py tests/test_contracts.py
just test
| Status | Count |
|---|---|
| ✅ Passed | 570 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 69s |
[0.18.0] - 2026-05-04
[0.17.3] - 2026-05-04
Added
POST /api/supervaizer/registration/refresh— Adds an authenticated controller endpoint that lets Studio request asynchronous re-registration. The route requires write-scope API-key access, reuses the existing supervisor account registration flow, and is advertised through the controller contract asController.POST_CONTROLLER_REGISTRATION_REFRESH.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 564 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 69s |
[0.17.2] - 2026-05-03
Added
POST /api/supervaizer/agents/{agent_slug}/status— Controller contract addsController.POST_AGENT_STATUS; HTTP handler returns the agent'sjob_statusresult as aJobResponse(job id, status, message, payload). OpenAPI lists explicit 200 (JobResponse) and error responses (ErrorResponsefor 400/404/500). Returns 404 whenjob_statusyields no result.
Changed
routes.py— synchronous agent hooks off the event loop —job_stop,job_status, and the start flow'sdynamic_choices_callbackrun insideasyncio.to_threadso blocking synchronous agent code does not stall the async server.routes.py/ OpenAPI — AgentPOST /statussuccess payload is aJobResponsewith explicit HTTP 200 (replacing the previousAgentResponse-shaped merge).case.py— logging — Routine case-method logs demoted from INFO to DEBUG to reduce noise under normal operation.agent.py— docstrings —Agent._execute,job_stop, andjob_statusdocument synchronous hook behavior and that the controller invokes them from a worker thread.AGENTS.md/ repo hygiene — Dropped generatedAGENTS.compiled.md; Supervaizer's in-repo agent guide is consolidated inAGENTS.md.publish-pypi.yml— post-publish release automation — After PyPI publish, CI now runs the same GitHub release flow asjust gh-release(tools/gh-release-latest-tag.sh) to create/update and mark the latest release from the newestorigin/maintag.publish-pypi.yml— branch reconciliation in CI — Added an automaticmain -> developmerge-back step after publish/release so long-lived branch history stays synchronized without manual follow-up.
Fixed
- GitHub Actions Node 20 deprecation warnings — Upgraded workflow action majors across CI/release/publish pipelines:
actions/checkout@v5,actions/setup-python@v6, andastral-sh/setup-uv@v7to avoid Node 20 runtime deprecation warnings and align with Node 24 transition.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 560 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 69s |
[0.17.1] - 2026-04-26
Fixed
server.py— startup lifespan migration — Replaced deprecated@app.on_event("startup")with a properasynccontextmanagerlifespan passed toFastAPI(lifespan=...). EliminatesDeprecationWarningfrom FastAPI 0.100+.account_service.py— atexit robustness —close_httpx_client_syncnow guards theaclose()call withgetattr(_httpx_client, "aclose", None)to preventAttributeErrorwhen the module-level client is a synchttpx.Clientin older-installed environments.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 559 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 74s |
[0.17.0] - 2026-04-26
Changed
- Async control-event HTTP client —
account_service.send_event,Accountevent helpers, and case event-reporting methods now usehttpx.AsyncClientand must be awaited in async agents. Explicit_syncshims remain for CLI, startup, and synchronous controller methods. See RFC-002 for details.
Tests
just test
| Status | Count |
|---|---|
| ✅ Passed | 559 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | |
| ⏱️ with cov | 102s |
Coverage
| Name | Stmts | Miss | Cover |
|---|---|---|---|
| src/supervaizer/init.py | 23 | 3 | 87% |
| src/supervaizer/version.py | 3 | 0 | 100% |
| src/supervaizer/access/init.py | 4 | 0 | 100% |
| src/supervaizer/access/api_auth.py | 38 | 1 | 97% |
| src/supervaizer/access/client_ip.py | 37 | 7 | 81% |
| src/supervaizer/access/tailscale.py | 23 | 2 | 91% |
| src/supervaizer/account.py | 122 | 15 | 88% |
| src/supervaizer/account_service.py | 80 | 2 | 98% |
| src/supervaizer/admin/routes.py | 549 | 190 | 65% |
| src/supervaizer/admin/workbench_routes.py | 380 | 256 | 33% |
| src/supervaizer/agent.py | 354 | 80 | 77% |
| src/supervaizer/case.py | 267 | 64 | 76% |
| src/supervaizer/cli.py | 210 | 75 | 64% |
| src/supervaizer/common.py | 142 | 4 | 97% |
| src/supervaizer/contracts.py | 168 | 3 | 98% |
| src/supervaizer/data_resource.py | 70 | 0 | 100% |
| src/supervaizer/data_routes.py | 98 | 21 | 79% |
| src/supervaizer/deploy/init.py | 2 | 0 | 100% |
| src/supervaizer/deploy/cli.py | 104 | 46 | 56% |
| src/supervaizer/deploy/commands/init.py | 2 | 0 | 100% |
| src/supervaizer/deploy/commands/clean.py | 158 | 17 | 89% |
| src/supervaizer/deploy/commands/down.py | 61 | 12 | 80% |
| src/supervaizer/deploy/commands/local.py | 214 | 15 | 93% |
| src/supervaizer/deploy/commands/plan.py | 75 | 7 | 91% |
| src/supervaizer/deploy/commands/status.py | 100 | 41 | 59% |
| src/supervaizer/deploy/commands/up.py | 113 | 8 | 93% |
| src/supervaizer/deploy/docker.py | 186 | 23 | 88% |
| src/supervaizer/deploy/driver_factory.py | 20 | 0 | 100% |
| src/supervaizer/deploy/drivers/init.py | 13 | 4 | 69% |
| src/supervaizer/deploy/drivers/aws_app_runner.py | 221 | 157 | 29% |
| src/supervaizer/deploy/drivers/base.py | 82 | 8 | 90% |
| src/supervaizer/deploy/drivers/cloud_run.py | 205 | 125 | 39% |
| src/supervaizer/deploy/drivers/do_app_platform.py | 164 | 125 | 24% |
| src/supervaizer/deploy/health.py | 161 | 12 | 93% |
| src/supervaizer/deploy/state.py | 115 | 9 | 92% |
| src/supervaizer/deploy/utils.py | 24 | 0 | 100% |
| src/supervaizer/event.py | 40 | 1 | 98% |
| src/supervaizer/examples/local_server.py | 17 | 3 | 82% |
| src/supervaizer/instructions.py | 56 | 1 | 98% |
| src/supervaizer/job.py | 166 | 28 | 83% |
| src/supervaizer/job_service.py | 34 | 0 | 100% |
| src/supervaizer/lifecycle.py | 153 | 3 | 98% |
| src/supervaizer/parameter.py | 79 | 7 | 91% |
| src/supervaizer/protocol/init.py | 2 | 0 | 100% |
| src/supervaizer/protocol/a2a/init.py | 3 | 0 | 100% |
| src/supervaizer/protocol/a2a/model.py | 37 | 5 | 86% |
| src/supervaizer/protocol/a2a/routes.py | 35 | 3 | 91% |
| src/supervaizer/routers/init.py | 4 | 0 | 100% |
| src/supervaizer/routers/api.py | 18 | 1 | 94% |
| src/supervaizer/routers/private.py | 10 | 0 | 100% |
| src/supervaizer/routers/public.py | 22 | 5 | 77% |
| src/supervaizer/routes.py | 333 | 60 | 82% |
| src/supervaizer/server.py | 282 | 84 | 70% |
| src/supervaizer/server_utils.py | 25 | 0 | 100% |
| src/supervaizer/storage.py | 160 | 12 | 92% |
| src/supervaizer/telemetry.py | 40 | 0 | 100% |
| src/supervaizer/utils/init.py | 2 | 0 | 100% |
| src/supervaizer/utils/version_check.py | 27 | 6 | 78% |
| ------------------------------------------------- | ----- | ---- | ----- |
| TOTAL | 6133 | 1551 | 75% |
[0.16.0] - 2026-04-25
Added
- Controller contract metadata for Studio —
server.registernow advertisescontroller_contract_version,/apibase path, and canonical endpoint templates so Studio can route without hardcoded Supervaizer paths. The same contract is available atGET /api/supervaizer/contract. - DataResource request context — DataResource callbacks can opt into a
contextkeyword with workspace, mission, agent, and request identifiers while legacy callbacks continue to work unchanged. - CaseNodes update helpers —
CaseNodes.node_index()andCaseNodes.make_update()derive step indexes from the declared node set instead of requiring consumers to maintain a separate index map.
Changed
- DataResource fields can be marked sensitive —
DataResourceField.sensitiveis included in registration payloads for Studio masking.
Tests
- New:
tests/test_contracts.pyfor contract endpoint templates, schema export, import safety, resolver behavior, and DataResource context headers. - New:
tests/test_case.pycoverage forCaseNodes.node_index()andCaseNodes.make_update(). - Updated:
tests/test_routes.pyto verify DataResource callbacks receiveDataResourceContextfrom forwardedX-Supervaize-*headers. - Updated:
tests/test_server.pyto assert registration info and/api/supervaizer/contractexpose matching/apicontract metadata. - Deleted: none.
just test
| Status | Count |
|---|---|
| ✅ Passed | 514 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 01:03 |
[0.15.1] - 2026-04-20
Fixed
TemplateResponseStarlette 0.50 compatibility — Updatedrouters/public.pyandroutes.pyto use the newTemplateResponse(request, name, context)API. The old two-argument formTemplateResponse(name, context)was removed in Starlette 0.50.0, causing aTypeError: unhashable type: 'dict'crash on everyGET /request.
[0.15.0] - 2026-04-20
Added
-
supervaizer.accessmodule — New package with three focused sub-modules for centralized access control:client_ip.py—_extract_client_ip(scope)extracts the real client IP from ASGI scope, honoringTRUSTED_PROXIES(env var, comma-separated CIDRs) to safely parseX-Forwarded-For; returns""on any parse error (fail-closed).tailscale.py—require_tailscaleFastAPI dependency enforces that requests originate from the Tailscale CGNAT range100.64.0.0/10; raises HTTP 403 orWebSocketException(1008)on denial; logs vialog_access_denied_tailscale.api_auth.py—require_api_key/require_scopeFastAPI dependencies for machine-to-machine auth with a hierarchical scope model (writeimpliesread).API_KEYSregistry is empty by default;SUPERVAIZER_API_KEYenv var is pre-loaded as awrite-scope entry at import time.
-
supervaizer.routersmodule — Three router factories that replace scattered per-routeSecurity(...)calls:public_router— unauthenticated surface for home page (/) and A2A discovery (/.well-known/*).private_router(prefix/manage) — admin UI and workbench WebSocket, gated byrequire_tailscaleat router level.api_router(prefix/api) — machine-to-machine surface (/api/supervaizer/…,/api/agents/{slug}/…), gated byrequire_api_key; write-mutating endpoints additionally enforcerequire_scope("write").
-
log_access_denied_tailscaleandlog_access_denied_apihelpers insupervaizer.common— structuredWARNINGlog entries for every denied request, including IP, path, reason, and a truncated key preview (never the raw key value).
Changed
-
Admin UI moved from
/adminto/manage— All admin routes, workbench, and HTML template links updated.private_router(prefix/manage) gates the surface with Tailscale-only access instead of the previousAdminIPAllowlistMiddleware+ API-key combo. -
API routes moved from
/supervaizer/…to/api/supervaizer/…— All machine-to-machine endpoints now live under the/apiprefix provided byapi_router. Clients must update base paths accordingly. -
AdminIPAllowlistMiddlewareremoved — Replaced byrequire_tailscaleat router level. Theadmin/ip_allowlist.pymodule is deleted. -
Per-route
Security(server.verify_api_key)removed fromroutes.pyanddata_routes.py— Authentication is now enforced once at theapi_routerlevel. -
Admin auth simplified to Tailscale-only —
verify_admin_access,?key=query-param handling, and console-token generation/validation are removed fromadmin/routes.pyandadmin/workbench_routes.py.
Security
- Removed hard-coded default API keys —
API_KEYSis now empty at startup; no credentials ship with the package. OnlySUPERVAIZER_API_KEY(operator-supplied env var) populates the registry.
Tests
- New:
tests/test_access_client_ip.py,tests/test_access_tailscale.py,tests/test_access_api_auth.pycovering the new access layer. - Updated:
test_routes.py,test_routes_case_update.py,test_data_resource.py— paths prefixed with/api. - Updated:
test_admin_routes.py,test_workbench_routes.py— prefix/admin→/manage; Tailscale gate bypassed viadependency_overrides. - Deleted:
test_admin_ip_allowlist.py— coverage moved to new access tests.
just test
| Status | Count |
|---|---|
| ✅ Passed | 505 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 01:07 |
[0.14.2] - 2026-04-16
Added
- Automatic data resource route mounting at startup —
Servernow mounts generated CRUD routers for any agent that declaresdata_resources, so endpoints are available immediately after server boot without extra manual wiring.
Fixed
-
DataResource.registration_infonow includes computeddisplay_labelper field — Resource field payloads sent to Studio now expose resolved labels (display_label) instead of only raw model dumps, ensuring proper field naming in the UI. -
JobStartConfirmationEventis emitted afterjob_startexecution metadata is available — The confirmation event is now sent afterjob.metadatais populated from thejob_startresponse payload, so Studio receives complete metadata in the start confirmation event.
Unit Tests Results
just test
| Status | Count |
|---|---|
| ✅ Passed | 500 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | ~70s |
[0.14.1] - 2026-04-15
[0.14.0] - 2026-04-14
Added
-
DataResourceclass — Declares agent-owned CRUD endpoints exposed to Studio withname,entity_type,description,operations(list of CRUD operations),importable(bulk import support), anddeletableflags. -
DataResourceFieldclass — Describes field schema withname,type,description,editable, andvisibleattributes for validated rendering in Studio forms. -
FieldTypeenum — Validated field types:STRING,INTEGER,BOOLEAN,DATE,DATETIME,TEXT,EMAIL,URLfor consistent data handling across agents and Studio. -
Editableenum — Controls Studio form behaviour per field:ALWAYS(edit in all forms),CREATE_ONLY(edit only on creation),NEVER(read-only display). -
metadata: dictonAbstractJobandCaseAbstractModel— Arbitrary metadata flows throughregistration_infoto Studio, enabling agents to attach custom context and tracking data to jobs and cases. -
data_resources: list[DataResource]onAgent— Included inregistration_infofor Studio to discover and render CRUD interfaces for agent-managed data. -
Auto-generated FastAPI CRUD routes — For each declared
DataResourceoperation, Supervaizer auto-mounts routes (GET, POST, PATCH, DELETE) at/agents/{slug}/data/{resource}/.... -
Bulk import route — When
importable=Trueon aDataResource, aPOST /data/{resource}/import/route accepts CSV or JSON for batch creation, enabling Studio to load data in bulk.
Unit Tests Results
just test
| Status | Count |
|---|---|
| ✅ Passed | 492 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | ~70s |
[0.13.3] 2026-04-14
Added
-
CaseNodeUpdate.upsertandCase.patch_step— Optional step update path for Studio: whenupsertis true, the existing case step at the same index is updated instead of appending.Case.patch_step(index, update)setsindexandupserton the update, sendssend_update_case, and replaces the matching entry inCase.updates. Serialized inCaseNodeUpdate.registration_infofor the controller payload. -
Human answer with
casestep_index—POST /jobs/{job_id}/cases/{case_id}/update: ifrequest.answerincludescasestep_index, the controller callscase.patch_step(int(casestep_index), update)and runsPersistentEntityLifecycle.handle_event(..., INPUT_RECEIVED)instead ofreceive_human_input. Omitcasestep_indexfor the previous append/receive-human-input behavior. -
Tests —
tests/test_routes_case_update.pycovers job 404, workbench-stylehuman_answerparams (includingcasestep_indexstripped fromfields), single owning agent vs multiple agents, and skip whenjob.agent_nameis not on the server.
Changed
-
Dynamic choices request context —
POST .../start/dynamic_choicesnow passesworkspace_slugthrough todynamic_choices_callbackalongsideworkspace_idandmission_id(Supervaize Studio sends it in the JSON body). -
POST /jobs/{job_id}/cases/{case_id}/update(human_answer) — Resolves the job with in-memoryJobs().get_jobfirst, then persisted (include_persisted=True) if missing. Returns 404 when the job does not exist. Dispatcheshuman_answeronly for the job owner viaserver.get_agent_by_name(job.agent_name)andagent._execute(...), using the same parameter shape as the workbench HITL route (fields,context,payload,job_id,case_id, optionalmessage). Stripscasestep_indexfromfieldsfor the hook. Runs the hook in a thread pool executor to avoid blocking the event loop.
Unit Tests Results
just test
| Status | Count |
|---|---|
| ✅ Passed | 473 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | ~70s |
[0.13.1]
Added
ADMIN_ALLOWED_IPSfor admin UI — When set, only matching client IPs may access/admin(HTML, APIs, static files, WebSocket). Comma-separated IPs and optional CIDR notation; empty or unset allows all. Uses the first address inX-Forwarded-Forwhen present.- Dynamic choices for
AgentMethodField— Fields can now usedynamic_choicesinstead of staticchoicesto resolve options at runtime via a callback. Add adynamic_choices_callbackcallable (signature:(method_name: str, context: dict) -> dict[str, list[tuple[str, str]]]) to theAgentconstructor and adynamic_choiceskey to yourAgentMethodField. Supervaize Studio fetches choices from the newPOST /supervaizer/agents/{slug}/start/dynamic_choicesendpoint (withworkspace_id,workspace_slug, andmission_idin the request body) when rendering the job start form. Staticchoicesanddynamic_choicesare mutually exclusive on a field. See Dynamic Choices guide.
Unit Tests Results
just test
| Status | Count |
|---|---|
| ✅ Passed | 464 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 65s |
[0.12.0]
Added
-
Custom routes — Agents can mount their own FastAPI
APIRoutervia the newcustom_routesfield onAgent. Supervaizer mounts them under the API router at/api/agents/{slug}/...(paths defined on the nested router append after that prefix) without inspecting or managing the routes. Enables agents to expose tool endpoints, webhooks, or any HTTP API alongside the workbench. -
Scheduled steps —
CaseNodeUpdategainsscheduled_at,scheduled_method,scheduled_params,scheduled_statusfields. Steps withscheduled_atare deferred until the scheduled time. A background executor polls every 60 seconds and calls the agent method automatically. The workbench shows countdown, "Execute now", and "Cancel" controls on pending scheduled steps. Enables time-based orchestration (call scheduling, retries with backoff, follow-up actions).- Model:
CaseNodeUpdate.scheduled_at / scheduled_method / scheduled_params / scheduled_status - Property:
CaseNodeUpdate.is_scheduledreturnsTruewhenscheduled_atis set - Executor:
_run_scheduled_step_loop— background asyncio task, polls every 60s - Routes:
POST .../execute,POST .../cancel,PATCH .../schedulefor step management - UI: status badges (pending/executing/completed/failed/cancelled), execute now / cancel buttons
Case.cancel_scheduled_steps()— cancels all pending steps on job stopCases.get_due_scheduled_steps()— returns steps wherescheduled_at <= now()and status ispending
- Model:
-
AgentResponseexport —AgentResponseis now exported fromsupervaizer.__init__for use as a typed response model in custom routes and agent endpoints.
Fixed
- OpenAPI / JSON Schema (Pydantic 2.12+) — Building the full FastAPI schema (
GET /openapi.json, Swagger UI) could raisePydanticInvalidForJsonSchema: … CallableSchema. Three root causes fixed:AgentMethodAbstract.model_config["example_dict"]used"type": str(Python builtin) — changed to string"str"AgentResponsenested schemas not rebuilt after dependent models — addedAgentResponse.model_rebuild()afterCase.model_rebuild()insupervaizer/__init__.pyCaseNode.factorytyped asCallablewhich cannot appear in JSON Schema — changed toAny(behaviour unchanged)
[0.11.0]
-
Job Poll mechanism — New optional
job_pollmethod inAgentMethodsfor manual external service polling. When defined, the workbench shows a "Check for updates" button on active jobs. Clicking it calls the agent's poll handler, which checks external services (email inboxes, call status APIs, etc.) and updates cases accordingly. Enables local development without webhooks — production uses real-time webhooks, local mode uses the poll button.AgentMethods: newjob_poll: AgentMethod | Nonefield- Route:
POST /workbench/jobs/{job_id}/polltriggers the agent's poll handler - UI: "Check for updates" button with loading state, conditionally rendered via
has_polltemplate variable - JS:
pollJob()inworkbench-form.jswith disable-during-request pattern
-
HITL double-click guard — All HITL buttons are disabled during submission via
_postAnswer(). Buttons getopacity-50 cursor-not-allowedwhile in flight and re-enable on error. Dialog HITLsubmitMessage/confirmDialogare now async, properly awaiting the form submission before resetting state. -
Monitor reply display — Step payloads with a
replykey render as a blue blockquote below the step row. Step payloads withapproved_contentrender as a green confirmed card. -
Monitor duration display —
step_durationformat now handles both numeric and string values, preventing Jinja2TypeErrorwhen duration comes from HITL form input. -
WebSocket terminal signal — Terminal job state sends a
terminalWS signal that keeps the connection idle, preventing reconnect loops. -
is_local_mode()helper — Centralized insupervaizer.common, replacing inlineos.environ.get("SUPERVAIZER_LOCAL_MODE")checks acrossaccount_service.py,server.py. -
dequefor log buffer —_workbench_log_bufferchanged fromlisttocollections.deque(maxlen=500), removing manual trim logic. -
Dialog HITL — New HITL type for interactive content review via chat interface. When a
CaseNodeUpdatepayload containssupervaizer_dialog, the workbench renders a conversation UI instead of a fixed form. Supports iterative refinement through LLM-powered feedback loops. Fields:content(JSON string or plain text),content_type(email/text/code),objective,instructions,messages(conversation history),confirm_label.- Template:
dialog_renderer.htmlwithrender_hitl_dialogandrender_dialog_confirmedmacros - JS:
submitDialogMessage(caseId, message)andconfirmDialog(caseId)inworkbench-form.js - Route:
workbench_routes.pydetectssupervaizer_dialogin AWAITING case payloads
- Template:
-
Local mode URL fixes —
supervaizer start --local --port Nnow correctly shows localhost URLs everywhere: CLI output, admin interface logs, storage, and uvicorn. Fixed by resolvingServer.__init__defaults from env vars at call time (not class definition time) and ensuring CLI-provided values take precedence over.envfile values. -
Local mode event skipping —
account_service.send_event()returns a no-opApiSuccesswhenSUPERVAIZER_LOCAL_MODE=true, preventing HTTP errors against the SaaS API during local development. -
Agent parameter env pre-fill — In local mode, the workbench auto-loads
.envvalues into agent parameter fields with green.envbadge indicators. Secret fields show a masked placeholder; non-secret fields display the value. Backend falls back to env values for empty fields on job submission. -
HTMX polling guard — Monitor template suppresses
hx-triggerpolling when a HITL dialog or form is active, preventing DOM overwrites while users interact with forms.
v0.10.27
-
Agent Workbench — Full-featured testing interface for agents directly from the admin panel. Four-zone layout with agent parameters, job control, execution monitor, and live console log. Supports starting/stopping jobs, real-time case and step tracking via HTMX polling, and Human-in-the-Loop (HITL) form rendering and submission. Job history panel lists all past executions with status badges.
- Backend:
workbench_routes.pywith 8 FastAPI endpoints (page, start, stop, status, monitor, console, HITL answer, job history) - Frontend:
workbench.html,workbench_monitor.html,workbench_console.html,workbench_jobs_list.html,workbench-form.js - Shared field renderer macros:
field_renderer.html
- Backend:
-
Local test mode (
--local) — Run the supervaizer server without Supervaize Studio credentials for local development and workbench testing. Includes built-in Hello World agent with configurable case count, optional HITL steps, andJobInstructions.check()support for graceful stop. Default API keylocal-dev, amber banner in admin UI.- CLI:
supervaizer start --local/just local - Agent:
examples/hello_world_agent.pywith_LocalAccount(no-op Studio stub) - Server factory:
examples/local_server.py
- CLI:
Changed
- Admin navigation — Workbench access moved from nav dropdown to per-agent cards with direct green "Workbench" button. Removed "New Agent" button from agents list.
- Admin auth — Refactored API key resolution to support local server instance (
_get_admin_api_key,_is_local_mode), with fallback chain: server state → env var → default.
Fixed
- CaseNode.factory now optional —
CaseNode.factoryfield changed from required toOptional[Callable] = None. Previously,factorywasexclude=True(correctly omitted from serialization), but still required by Pydantic validation. This causedAgentResponse(**agent.registration_info)to fail withField requirederrors on theGET /supervaizer/agentsroute, because the round-tripped dict never containedfactory. Agents with CaseNode-based workflows were unable to register. (#6)
Changed
- CI – Python package workflow: dependency install now uses
uv sync --extra dev --extra deploy(adds deploy extras for CI).
Unit Tests Results
| Status | Count |
|---|---|
| ✅ Passed | 433 |
| 🤔 Skipped | 0 |
| 🔴 Failed | 0 |
| ⏱️ in | 50s |
[0.10.19]
Added
- Server: optional local index.html – If a local
index.htmlexists, the server serves it for the home page response.
Changed
- Dependencies – Bumped
boto3/botocoreto 1.42.41 (lock file). Updatedruffto 0.15.0 and pre-commit config. - Admin index – Simplified displayed information in the admin index template.
- CI – PyPI publish workflow: added concurrency settings to cancel in-progress runs.
[0.10.18]
Added
- SUPERVAIZER_PRIVATE_KEY –
_get_or_create_private_keyreads key from env or generates and sets it. Admin dashboard shows a development-only warning (not for production exposure).
Changed
- Refactor – Code formatting and trailing whitespace cleanup (admin routes, server, examples, tests, templates).
[0.10.17]
Added
-
SUPERVAIZER_PRIVATE_KEY from env if set; else create key and set env.
-
Admin: live server and data when no persistence – When there is no persistent storage (e.g. Vercel, serverless), the admin dashboard and agents page no longer fail. Server status, server config, and agents use the live server instance (
app.state.server) when storage has no ServerInfo. Dashboard stats, jobs list, cases list, and recent activity use live Jobs/Cases registries when storage is in-memory and empty.
Changed
- Register with supervisor (no frontend API key) – The "Register with supervisor" button now calls the backend without any API key. The backend sends the SERVER_REGISTER event to SUPERVAIZE_API_URL; no authentication is required from the frontend for this action.
- Admin server/agents fallback – Server info and agents are read from storage first, then from the live server when storage has no ServerInfo (e.g. persistence disabled).
get_server_statusandget_server_configurationaccept an optionalrequestfor the live fallback.
Fixed
- Admin: API key "None" in URLs – When
SUPERVAIZER_API_KEYis unset, the template no longer renders the literal string"None"(e.g. indata-admin-key). SessionStorage no longer stores"None"from?key=None, and the frontend treats the string"None"as no key where applicable.
Unit Tests Results
| Status | Count |
|---|---|
| ✅ Passed | 419 |
| 🤔 Skipped | 6 |
| 🔴 Failed | 0 |
| ⏱️ in | 53.16s |
[0.10.11]
Added
- Optional data persistence (default off) – Data is no longer persisted to file by default, so the server runs correctly on Vercel and other serverless platforms where the filesystem is ephemeral.
Changed
- Controller unreachable – When the Supervaize controller server is not available (connection refused or timeout), event send now fails gracefully with a short, clear error message instead of dumping the full payload and traceback. Logs:
Supervaize controller is not available at {url}. Connection refused or timed out. Is the controller server running?and the event type/exception.- Set
SUPERVAIZER_PERSISTENCE=true(or1/yes) to enable file persistence. - CLI:
supervaizer start --persistenables persistence for that run. - Explicit
StorageManager(db_path=...)in code still uses file storage (e.g. tests). - See 2025_08_PERSISTENCE.md for configuration.
- Set
Unit Tests Results
| Status | Count |
|---|---|
| ✅ Passed | 419 |
| 🤔 Skipped | 6 |
| 🔴 Failed | 0 |
| ⏱️ in | 55.28s |
[0.10.4]
- Relax some dependencies requirements
[0.10.2]
Changed
- 🐍 Python 3.13 Support - Added Python 3.13 compatibility
- Updated package classifiers to include Python 3.13
- Build process now uses Python 3.13 for wheel generation
- CI test matrix includes Python 3.13
- Wheels built with Python 3.13 are compatible with both Python 3.12 and 3.13
[0.10.0]
Added
-
🚀 Cloud Deployment CLI - Complete automated deployment system for Supervaizer agents
- Full implementation of RFC-001: Cloud Deployment CLI
- Support for three major cloud platforms:
- Google Cloud Run with Artifact Registry and Secret Manager
- AWS App Runner with ECR and Secrets Manager
- DigitalOcean App Platform
- New deployment commands:
supervaizer deploy plan- Preview deployment actions before applyingsupervaizer deploy up- Deploy to cloud platform with automated build, push, and verificationsupervaizer deploy down- Tear down deployment and clean up resourcessupervaizer deploy status- Check deployment status and healthsupervaizer deploy local- Local Docker testing with docker-composesupervaizer deploy clean- Clean up deployment artifacts and state
- Automated Docker Workflow: Build → Push → Deploy → Verify
- Secret Management: Secure handling of API keys and RSA keys via cloud provider secret stores
- Health Verification: Automatic health checks at
/.well-known/healthendpoint - Idempotent Deployments: Safe create/update operations with rollback on failure
- Local Testing: Full Docker Compose environment for pre-deployment testing
- See Local Testing Documentation for details
-
Agent Instructions Template - New HTML page served by FastAPI for Supervaize integration instructions
- Accessible at
/admin/supervaize-instructions - Provides step-by-step setup guide for agents
- Accessible at
-
Version Check Utility - Automatic check for latest Supervaizer version
- Helps users stay up-to-date with latest features and fixes
- Located in
supervaizer.utils.version_check
-
Enhanced Admin Interface
- New agents listing page with grid view
- Improved agent detail views
- Better navigation and UI consistency
Changed
-
🔄 Protocol Unification - Removed ACP protocol in favor of unified A2A protocol
- Removed
src/supervaizer/protocol/acp/directory and all ACP-specific code - Removed
acp_endpointsparameter from Server class - Removed ACP route registration and test files
- Updated all documentation to reflect A2A-only support
- The A2A protocol has evolved to incorporate features from multiple agent communication standards, including the former ACP
- All A2A protocol links updated to https://a2a-protocol.org/
- Breaking Change:
acp_endpointsparameter no longer accepted in Server initialization
- Removed
-
📦 Dependency Optimization - Cloud SDKs moved to optional dependencies
- Base package size significantly reduced
- Cloud deployment dependencies now optional:
pip install supervaizer[deploy] - Optional
deploygroup includes: boto3, docker, google-cloud-artifact-registry, google-cloud-run, google-cloud-secret-manager, psutil - Removed unused
pymongodependency - Updated dependency versions for better compatibility
-
Improved Error Handling - Enhanced API error responses with better context
-
Documentation Updates
- Added comprehensive deployment documentation
- Updated model reference documentation
- Improved README with deployment examples
- Updated 2025_08_PROTOCOLS.md to focus on unified A2A protocol
- Added Protocol Evolution section explaining ACP merger
Fixed
- API documentation errors corrected
- Improved type hints for
agent_parametersandcase_idsin job.py - Health logging optimized in A2A routes
Unit Tests Results
| Status | Count |
|---|---|
| ✅ Passed | 415 |
| 🤔 Skipped | 6 |
| 🔴 Failed | 0 |
| ⏱️ in | 50.56s |
Migration Notes
- ACP Protocol Removal: If your code uses
acp_endpoints=Trueparameter, remove it from Server initialization. The A2A protocol now provides unified agent communication. - If you need deployment features, install with:
pip install supervaizer[deploy] - For development, install with:
pip install supervaizer[dev,deploy] - No other breaking changes to existing APIs or functionality
[0.9.8]
Added
- Parameter Validation System: Added comprehensive parameter validation for job creation with clean error messages
- New
validate_parameters()method inParametersSetupclass for agent parameter validation - New
validate_method_fields()method inAgentMethodclass for job field validation - Two separate validation endpoints for different validation needs:
/validate-agent-parameters- Validate agent configuration parameters (secrets, API keys, etc.)/validate-method-fields- Validate job input fields against method definitions
- Support for validating both job fields and encrypted agent parameters
- Clean error messages with specific details about invalid parameter types and missing required parameters
- New
Fixed
- Execution of
supervaizer startwas not maintaining the main namespace so the fastapi server was never starting. Replaced execution by sub-process. - Type of agent.choice. #TODO: test and decide which to keep (list[str] or list [tuple[str,str]])
- When supervisor_account is provided, A2A endpoints are automatically activated, because Supervaize needs to be able to trigger the healthchecks. -
export_openapi.pytool to generate openapi.json (for docusaurus documentation) - automation in docusaurus to do.
Changed
-
Parameter Validation System: Refactored to provide separate validation endpoints for different concerns
- Agent Parameters: Now validated separately through
/validate-agent-parametersendpoint - Method Fields: Now validated separately through
/validate-method-fieldsendpoint - Clean Architecture: Removed legacy endpoint for cleaner, more focused API design
- Code Deduplication: Eliminated redundant validation code in job start endpoints
- Clearer Separation: Agent configuration validation vs. job input validation are now distinct operations
- Agent Parameters: Now validated separately through
-
pytest does not run with coverage by default (change in pyproject.toml)
Unit tests results
| Status | Count |
|---|---|
| ✅ Passed | 308 |
| 🤔 Skipped | 6 |
[0.9.6]
- Public release to Pypi
- Fixed the github workflows
- Improve README.md
[0.9.5]
Fixed
- Setup : missing
py.typedin pyproject - clarified public_url (replaced registration_host by public_url)
- changed "supervaizer install" to "supervaizer scaffold"
Added
gen_model_docs.py: tool for documentation generation - see disclaimer
Unit tests results
| Status | Count |
|---|---|
| ✅ Passed | 277 |
| 🤔 Skipped | 6 |
[0.9.4]
Added
- CICD : release, deploy
gen_model_docs.py: to generate the documentation of the models.
Changed
- Moved "example" to
src/supervaizer - Improved and Moved some documentation to
docs - Added
python-package.ymlgithub action, triggered on push / PR of "develop" branch
[0.9.3]
Added
- Data persistence with tinyDB
- Admin UI with fastAdmin
- Dynamic content on:
- Server page
- Agent
- Jobs
- Cases
- Add persisted data to job status check.
Changed
- Parameter.to_dict : override to avoid storing secrets.
- Removed Case Nodes
- Improved test coverage : accounts, admin/routes,
Unit tests results
| Status | Count |
|---|---|
| 🤔 Skipped | 6 |
| ⚠️ Failed | 0 |
| ✅ Passed | 281 |
Emoji Legend 🌅 Template 🏹 Service 👔 Models 🐛 Bug 🛣️ Infrastructure/CICD 🔌 API 💼 Admin 📖 Documentation 📰 Events 🧪 Tests 🧑🎨 UI/Style 🎼 Controller
Uploaded on 2026-11-06 15:07:19