No agent ships without a verdict.
ReleaseCourt is a Band-powered review room for AI agents before deployment. It accepts a generic Release Packet v1 YAML/JSON upload, freezes the release identity, runs Security Red-Team -> Evaluation Agent -> Release Judge, and records a deterministic verdict plus the human decision that follows it.
The flagship demo candidate is RefundBot, but the implemented packet flow also supports generic candidates through built-in, mock, and HTTP adapters. Band/Thenvoi is the real inter-agent coordination layer when enabled; the local event store mirrors sanitized events for replay, UI, idempotency, and persistence.
- Release Packet v1 upload as YAML or JSON with strict validation and 256 KiB size bound.
- Immutable packet hash and release id; duplicate packet uploads return the existing release.
- Built-in, mock, and HTTP candidate adapters; HTTP execution is bounded and SSRF-guarded.
- Real Band Review Room coordination with Thenvoi SDK workers for Security Red-Team, Evaluation Agent, and Release Judge.
- Deterministic verdict authority; optional OpenAI adaptive/remediation enrichment is advisory only.
- Bounded local continuation when Band degrades, without rerunning completed stages.
- Visible Review Room replay from JSONL locally or Postgres in production.
- Human dispositions:
APPROVE,REJECT, andREQUEST_CHANGES. - Cycle 2 fixed re-review preserves the original case, room, and
candidate_release_idlineage. - Idempotency and duplicate prevention for packet releases, review launch, handoffs, signoff, and re-review.
flowchart LR
Judge["Human judge"] --> UI["React/Vite Review Room"]
UI --> API["FastAPI backend"]
Packet["Release Packet v1 YAML/JSON"] --> API
API --> Identity["Immutable packet + release identity"]
Identity --> Runner["Candidate runner: built-in / mock / HTTP"]
API --> Band["Band/Thenvoi room"]
Band --> Security["Security Red-Team"]
Security --> Eval["Evaluation Agent"]
Eval --> Verdict["Release Judge"]
Runner --> Security
Verdict --> Engine["Deterministic verdict engine"]
API --> OpenAI["Optional OpenAI advisory enrichment"]
Engine --> Store["JSONL local mirror or Postgres"]
OpenAI --> Store
Band --> Store
Store --> UI
UI --> Human["APPROVE / REJECT / REQUEST_CHANGES"]
- Upload
examples/release_packets/travel_agent_vulnerable.yaml, create a release, and start review from/packets/releases/{release_id}/review. - Confirm the same packet uploaded twice returns the same immutable
release_id. - Confirm invalid fixtures reject cleanly and create no release:
invalid_embedded_secret.yamlandinvalid_unsupported_adapter.yaml. - Watch Security -> Evaluation -> Judge events replay in the Review Room timeline.
- Record
REQUEST_CHANGES, then run the fixed Cycle 2 path and verify the same case/room lineage remains visible. - Stop a Band worker and verify local degraded continuation resumes only the missing stage.
cd D:\ReleaseCourt\backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
python -m uvicorn app.main:app --reloadOpen http://localhost:8000/health and http://localhost:8000/docs.
cd D:\ReleaseCourt\frontend
npm install
npm run devOpen http://localhost:5173.
From the repository root:
.\scripts\run_demo_band.ps1
.\scripts\stop_demo_band.ps1
.\scripts\reset_demo.ps1run_demo_band.ps1 starts the backend, all three Band workers, and the frontend with a shared demo JSONL runtime. It requires backend\.env, backend\.venv, and backend\agent_config.yaml copied from agent_config.yaml.example.
examples/release_packets/travel_agent_vulnerable.yamlexamples/release_packets/travel_agent_fixed.yamlexamples/release_packets/http_travel_agent.yamlexamples/release_packets/invalid_embedded_secret.yamlexamples/release_packets/invalid_unsupported_adapter.yaml
Supported packet adapters are builtin, mock, and http.
Current suite totals:
- Backend:
947 passing - Frontend:
128 passing
Run locally:
cd D:\ReleaseCourt\backend
python -m pytest -v
python -m ruff check .cd D:\ReleaseCourt\frontend
npm run test
npm run lint| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Liveness |
GET |
/health/ready |
Persistence readiness |
GET |
/demo/templates |
Demo candidate templates and Band mode |
POST |
/demo/cases |
Create a demo case |
POST |
/demo/cases/{case_id}/review |
Start the active review cycle |
POST |
/demo/reset |
Guarded demo reset when DEMO_MODE=true |
POST |
/packets/validate |
Validate Release Packet v1 without persistence |
POST |
/packets/releases |
Persist immutable packet release |
GET |
/packets/releases/{release_id} |
Fetch release and normalized packet |
POST |
/packets/releases/{release_id}/review |
Launch packet review |
GET |
/cases/{case_id}/timeline |
Review Room replay |
POST |
/cases/{case_id}/signoff |
Human APPROVE, REJECT, or REQUEST_CHANGES |
POST |
/cases/{case_id}/rereview |
Start fixed Cycle 2 re-review |
POST |
/candidate-manifests/validate |
Validate legacy AUT manifest |
POST |
/candidates |
Register candidate identity |
POST |
/candidates/{candidate_id}/releases |
Register immutable AUT release |
backend/ FastAPI app, Band workers, packet pipeline, persistence
frontend/ React/Vite Review Room cockpit
examples/release_packets Release Packet v1 examples and invalid fixtures
scripts/ Windows demo, worker, stop, restart, and reset scripts
docs/ Supporting project notes
render.yaml Render backend deployment template
Local development defaults to PERSISTENCE_BACKEND=jsonl and writes under .releasecourt/. Production uses PERSISTENCE_BACKEND=postgres with DATABASE_URL; the app does not silently fall back to JSONL when Postgres is selected.
render.yaml deploys the backend from backend/, runs Uvicorn on $PORT, and uses /health/ready. Frontend deployment should set VITE_API_BASE_URL to the backend URL and configure backend CORS_ALLOWED_ORIGINS to the production frontend origin.
- No authentication or verified reviewer identity yet.
- No realtime subscription layer; the frontend polls the backend timeline.
- No PDF export, RAG, deployment automation, or additional business/privacy review agents.
- JSONL is for local/demo persistence, not multi-worker production storage.
- OpenAI enrichment can improve advisory context but cannot override deterministic verdicts.