Skip to content

Decision Studio Web App, MCP Server & HTTP Gateway API

Beyond the command-line evaluation harness (dgem decide, dgem bench-*), dgem ships as a unified HTTP API Gateway, Lit WebComponents Decision Studio, Scale-to-Zero GPU Cold-Start Orchestrator, and Model Context Protocol (MCP) Server in a single self-contained Go binary (studio.DistFS() embedded).


flowchart LR
    subgraph Clients["Four Ways to Interact with dgem"]
        UI["1. Decision Studio Web App\nBrowser UI (Lit WebComponents)\nhttp://localhost:8090/"]
        MCP["2. AI Agents via MCP\nGemini CLI · Claude · Cursor\ndgem mcp (stdio) & POST /mcp"]
        REST["3. Microservices & curl\nSimplified REST JSON API\nPOST /api/decide/{template}"]
        CLI["4. Terminal & CI/CD\nGo CLI & Benchmark Suites\ndgem decide / dgem bench-*"]
    end

    subgraph Gateway["dgem serve / dgem mcp Gateway"]
        CAT["26+ .json.tmpl Policy Catalog\n(core · calibration · multimodal · rerank)"]
        WARM["Scale-to-Zero GPU Cold-Start\nOrchestrator & IAM/IAP Token Minter"]
        OTEL["OpenTelemetry & Cloud Trace\nSpan Waterfall Ring Buffer"]
    end

    subgraph Backends["DiffusionGemma GPU Backends"]
        CR["Serverless Cloud Run GPU\n1× RTX Pro 6000 (48GB) / 1× L4 (24GB)"]
        METAL["Local Apple Silicon Metal\ndiffgemma serve (:8080)"]
    end

    UI --> Gateway
    MCP --> Gateway
    REST --> Gateway
    CLI --> Gateway
    Gateway --> CR
    Gateway --> METAL
Interaction SurfaceCommand / EndpointTarget AudienceKey Capabilities
1. Decision Studio Web Appdgem serve →\rightarrow http://localhost:8090/Engineers, PMs, Security & AI ResearchersInteractive Lit WebComponents playground with live .json.tmpl policy catalog (core, calibration, multimodal, rerank), SigLIP bounding-box SVG canvas, one-click scale-to-zero GPU warmup, and OpenTelemetry span waterfall viewer.
2. Model Context Protocol (MCP)dgem mcp (stdio) or POST /mcp (Streamable HTTP)AI Agents (Gemini CLI, Claude Desktop, Cursor, Antigravity)Exposes 7 native MCP tools (decide_policy, locate_object, locate_bounding_boxes, decide_custom_questions, list_policy_templates, get_health_and_gpu_status, warmup_gpu) over both stdio and stateless Streamable HTTP.
3. HTTP Gateway REST APIPOST /api/decide/{template} & POST /v1/systemoneMicroservices, Web Backends, curl / Python scriptsExecute named .json.tmpl policies with a simple JSON variable map—no local dgem CLI or .json.tmpl files required by the caller. Automatically mints GCP IAM/IAP tokens and holds requests while scale-to-zero Cloud Run GPUs wake up.
4. dgem CLI & Benchmarksdgem decide, dgem ask, dgem bench-*Terminal workflows, CI/CD pipelines, Reproducible researchDirect single-pass decisions (--stats) and full evaluation harnesses (bench, bench-ecotone, bench-intents, bench-calibration, bench-bbox, bench-rerank).

Launching dgem serve starts the embedded Lit WebComponents Decision Studio alongside the REST API Gateway and Streamable HTTP MCP Server:

Terminal window
# Launch Decision Studio locally on port 8090 pointing at a Serverless Cloud Run GPU backend
./bin/dgem serve \
-u "https://<CLOUD_RUN_URL>/v1" \
--gcp-auth \
--port 8090

Open http://localhost:8090 in your browser. Decision Studio provides four integrated workspaces:

2.1 Live Policy Catalog & One-Click Preset Execution

Section titled “2.1 Live Policy Catalog & One-Click Preset Execution”
  • Automatically discovers all 26+ .json.tmpl decision policies across four categories:
    • core: support_triage, code_review, security_incident, contract_audit, agent_router, secops_conditional_dag, tn_disambiguation, intent_banking77 / intent_clinc150.
    • calibration: agent_step_drift, prompt_injection, grounding_claim_check, chaos_nli, ms_marco_relevance, civil_comments_toxicity, safety_toxicity, sentiment_emotion.
    • multimodal: bbox_localization, bbox_multi_object_detr, bbox_multi_object_set (SigLIP spatial grounding).
    • rerank: listwise_decision_rerank (12 simultaneous slots: 10 passages + 2 RAG security/abstention gates) and pointwise_rerank.
  • Selecting any policy automatically populates curated sample variables (ticket, diff, event_log, query, candidates, claim, context) and displays the live Go .json.tmpl source so users can test or customize policies in real time.

2.2 Answer Cards: Probabilities & Hesitation

Section titled “2.2 Answer Cards: Probabilities & Hesitation”

For every question evaluated in the single forward pass (steps=1, think=0), Decision Studio shows:

  • The chosen value and its probability pi=exp⁡(logprob)p_i = \exp(\text{logprob}), plus bars for the other allowed answers.
  • A Hesitation score from 0% (all probability on one answer) to 100% (a perfect tie): normalized Shannon entropy H~=H/ln⁡K\tilde{H} = H / \ln K, so 2-option and 26-option questions share one scale. It is labelled Clear (under 16%, the normalized threshold commonly used as a cascade gate), Somewhat unsure (16–50%), or Very unsure (above 50%). Hover to see the raw entropy in nats.
  • A summary strip: Model passes, Refinement steps, Response time, and Highest hesitation across the request.

Low hesitation is a strong signal but not a guarantee; option order can hide doubt. See Confidence beyond Shannon. The helper that computes hesitation lives in studio/src/hesitation.ts.

2.2b Concepts Walkthrough (Plain-Language)

Section titled “2.2b Concepts Walkthrough (Plain-Language)”

The Concepts tab is a self-serve, jargon-light introduction with five tabs: What’s a decision model?, One pass vs. word-by-word, When to trust an answer (hesitation-gating, plus an explainer on why option order is monitored rather than corrected), Built-in guardrails, and a Glossary (basics first, technical names collapsed). Simulations are labelled as illustrative. A Presenter mode toggle shows an optional talk track for live demos. A standalone copy (without the glossary) is published at visualizer.html.

When a multimodal/* policy (bbox_localization, bbox_multi_object_detr) is selected:

  • Users can pick from built-in fixtures/bbox/*.png test scenes or drag-and-drop custom images.
  • Decision Studio draws both the Continuous Softmax Expectation Box (c^m=∑kvkpm,k\hat{c}_m = \sum_k v_k p_{m,k}, green solid overlay) and the Discrete 21-Bin Argmax Box (amber dashed overlay) directly over the image, alongside per-edge entropy bars (ymin, xmin, ymax, xmax). These boxes are coarse (what dgem can do with images); the canvas is for inspecting dgem’s spatial readout, not for precise localization.

2.4 Scale-to-Zero GPU Cold-Start Orchestrator & OpenTelemetry Waterfall

Section titled “2.4 Scale-to-Zero GPU Cold-Start Orchestrator & OpenTelemetry Waterfall”
  • Live GPU State Pill: Polls GET /api/status to show whether the upstream Cloud Run GPU (NVIDIA RTX Pro 6000 48GB or NVIDIA L4 24GB) is warm_and_ready, warming_up (with elapsed seconds and progress bar), or scaled_to_zero.
  • One-Click GPU Wakeup (POST /api/warmup): Wakes a 0-instance Cloud Run GPU in the background and streams readiness to all connected browser tabs and MCP agents simultaneously (MarkGPUWarm() broadcast channel).
  • OpenTelemetry Trace Inspector (GET /api/traces): Displays the exact W3C trace_id, splitting total wall time into cold_start_wait_ms (GCS FUSE weight streaming) vs. gpu_forward_ms (pure DiffusionGemma forward pass), and exports spans to Google Cloud Trace when GOOGLE_CLOUD_PROJECT is set.

3. Model Context Protocol (MCP) Server (dgem mcp & POST /mcp)

Section titled “3. Model Context Protocol (MCP) Server (dgem mcp & POST /mcp)”

dgem includes a native Model Context Protocol (MCP) server built with the official Go MCP SDK (github.com/modelcontextprotocol/go-sdk/mcp). It supports two transports simultaneously:

  1. Standard Input/Output (stdio) via dgem mcp: Ideal for local AI coding assistants (Gemini CLI, Claude Desktop, Cursor, Antigravity).
  2. Streamable HTTP via POST /mcp on dgem serve: Ideal for remote Cloud Run deployments and multi-agent cloud orchestrators (Stateless: true, JSONResponse: true).

3.1 Configuring dgem mcp (Automatic ADC Auth) in Antigravity (~/.gemini/config/mcp_config.json), Gemini CLI (~/.gemini/settings.json), or Claude Desktop

Section titled “3.1 Configuring dgem mcp (Automatic ADC Auth) in Antigravity (~/.gemini/config/mcp_config.json), Gemini CLI (~/.gemini/settings.json), or Claude Desktop”

dgem mcp automatically reads Application Default Credentials (ADC: ~/.config/gcloud/application_default_credentials.json) in pure Go to mint and cache both OIDC id_tokens (accepted by Cloud Run IAP programmaticClients on your gateway) and OAuth2 access_tokens (for Vertex AI Dedicated Endpoint <endpoint-id>).

Option A: Connect to a Remote dgem serve Gateway via ADC (--remote)

Section titled “Option A: Connect to a Remote dgem serve Gateway via ADC (--remote)”
{
"mcpServers": {
"dgem-remote": {
"command": "/path/to/dgem/bin/dgem",
"args": [
"mcp",
"--remote",
"https://<your-dgem-gateway>/mcp"
]
}
}
}

Option B: Local stdio with Automatic ADC & vertex_first Routing

Section titled “Option B: Local stdio with Automatic ADC & vertex_first Routing”
{
"mcpServers": {
"dgem": {
"command": "/path/to/dgem/bin/dgem",
"args": [
"mcp"
],
"env": {
"DGEM_VERTEX_URL": "<ENDPOINT_ID>",
"GCP_PROJECT_NUMBER": "<PROJECT_NUMBER>",
"DGEM_REMOTE_URL": "https://<CLOUD_RUN_URL>/v1"
}
}
}
}

The MCP server runs inside your agent and calls the endpoints directly with ADC tokens. It needs to know where they are: DGEM_VERTEX_URL (with GCP_PROJECT_NUMBER for a bare endpoint ID) for Vertex AI, and DGEM_REMOTE_URL (or -u) for the Cloud Run /v1 URL used by cloudrun and vertex_first failover. Without them, requests go to http://127.0.0.1:8080/v1. If a gateway is already deployed, Option A is simpler.

Option C: Direct Streamable HTTP (dgem serve on localhost)

Section titled “Option C: Direct Streamable HTTP (dgem serve on localhost)”
{
"mcpServers": {
"dgem-local-http": {
"serverUrl": "http://localhost:8090/mcp"
}
}
}

Option D: Local stdio Targeting Apple Silicon Metal (--local)

Section titled “Option D: Local stdio Targeting Apple Silicon Metal (--local)”
{
"mcpServers": {
"dgem-local": {
"command": "/path/to/dgem/bin/dgem",
"args": [
"mcp",
"--local"
]
}
}
}

--local sends every call to the diffgemma engine at http://127.0.0.1:8080/v1 (change it with -u), with no cloud credentials or fallback. Start the engine first (make serve); see Run on a laptop.

opencode uses its own config format (~/.config/opencode/opencode.json or a project opencode.json). Any of the options above works; for example, Option D:

{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dgem-local": {
"type": "local",
"command": ["/path/to/dgem/bin/dgem", "mcp", "--local"],
"enabled": true
}
}
}

For Option A use "command": ["/path/to/dgem/bin/dgem", "mcp", "--remote", "https://<your-dgem-gateway>/mcp"]. Tools appear in opencode as dgem-local_decide_custom_questions and so on. Restart opencode after rebuilding bin/dgem: each session keeps its own dgem mcp process.

3.2 Complete Catalog of MCP Tools Exposed by dgem

Section titled “3.2 Complete Catalog of MCP Tools Exposed by dgem”
MCP Tool NameInput ArgumentsOutput Payload & Purpose
get_health_and_gpu_status{"backend": "vertex_first|vertex|cloudrun|local"} (optional)Returns gateway_healthy, gpu_available, gpu_state (warm_and_ready, warming_up, scaled_to_zero), active_backend, seconds_since_last_read, estimated_wake_seconds, gpu_tier, and templates_available for the selected backend (the server default if omitted). Agents call this first to check if the GPU is warm.
warmup_gpu{"wait_for_ready": true | false}Triggers a scale-from-zero wakeup (0 -> 1 instance) on the Cloud Run GPU backend. Set wait_for_ready: false to start streaming the 17.53 GiB safetensors over GCS FUSE asynchronously while the agent performs other work.
list_policy_templates{"category": "core" | "calibration" | "multimodal" | "rerank"} (optional)Lists the executable .json.tmpl decision policies found in the templates directory, with their required variables and sample_vars.
decide_policy{"template": "support_triage", "variables": {...}, "image": "...", "backend": "vertex_first|vertex|cloudrun|local", "vertex_url": "...", "cascade_mode": "off|entropy|on_miss", "cascade_threshold": 0.35, "cascade_model": "gemini-3.8-flash", "expected_answers": {...}, "suggest_expansions": false, "expansion_entropy": 0.35}Executes any named .json.tmpl policy in O(1)O(1) forward passes on vertex_first (default), vertex, cloudrun, or local (Apple Silicon Metal), with optional Stage 2 Gemini Cascade (gemini-3.8-flash) and taxonomy expansion. Returns answers (restricted-softmax probabilities per slot), diagnostics (per-slot entropy), and the summary fields in 3.3.
decide_custom_questions{"context": "...", "questions": [{"id": "...", "type": "boolean|choice|score", "question": "...", "options": [...]}], "backend": "vertex_first|vertex|cloudrun|local", "vertex_url": "...", "cascade_mode": "off|entropy|on_miss", "cascade_threshold": 0.35, "cascade_model": "gemini-3.8-flash", "expected_answers": {...}, "suggest_expansions": false, "expansion_entropy": 0.35}Evaluates an ad-hoc multi-slot decision schema dynamically constructed by the calling agent in 1 forward pass—the MCP equivalent of POST /v1/systemone—without needing a .json.tmpl file on disk. options is required for choice slots (at most 26). Returns the same fields as decide_policy.
locate_object{"image": "<url-or-data-uri>", "target": "checkout button", "mask": false, "gemini_model": "gemini-3.8-flash", "thinking": "low", "backend": "vertex_first"}Guided locate: dgem presence + 3×3 cell, then a Gemini 3.x box at LOW thinking; opt-in skip_h (skip Gemini when dgem is confidently absent) and hint (pass dgem’s cell) (box_1000, path, per-stage latency); optional SAM mask when DGEM_SAM_URL is set. Use this for precise boxes.
locate_bounding_boxes{"image": "<url-or-data-uri>", "target": "checkout button", "backend": "vertex_first|vertex|cloudrun", "vertex_url": "..."}Returns an approximate single-pass box (coarse, especially on screenshots; see the images guide): softmax_expectation_box_1000 (c^m=∑kvkpm,k\hat{c}_m = \sum_k v_k p_{m,k}) and discrete_argmax_box_1000 [ymin, xmin, ymax, xmax] in [0, 1000] coordinates plus per-edge entropy (coordinate_entropy_nats; flags wrong edges, does not detect occlusion). Use locate_object (Gemini) or a dedicated object detector for precise boxes. (Note: local Metal is text-only and does not support SigLIP vision).

decide_policy and decide_custom_questions return the same top-level fields as POST /api/decide, apart from trace_id and trace_spans (MCP calls aren’t traced through the gateway root span; see Observability).

FieldMeaning
answers.<slot>The chosen value (label, plus choice or score), its confidence, the probabilities of every allowed answer, and agreement / stderr across samples.
answers.<slot>.entropyShannon entropy of that slot’s probabilities, in nats. Convert it to Hesitation % by dividing by ln⁡K\ln K (KK = number of allowed answers); see 2.2.
diagnostics.questions.<slot>.entropy, .label_massThe engine’s per-read values. With diagnostics.constrained: true (the default serving mode) entropy equals the answer’s entropy and label_mass is always 1, so don’t gate on label_mass. With constrained: false (--no-constrained) entropy is over the top tokens at the slot and label_mass is the share of probability on the allowed labels.
max_entropyThe highest slot entropy in the request (nats). Use it as a single “is anything uncertain?” signal, for example to decide whether to ask a person or escalate with cascade_mode: "entropy".
wall_time_msTotal time spent in the tool call.
gpu_forward_msTime of the successful model call (the round trip to the engine).
cold_start_wait_msTime spent waiting for a scaled-to-zero backend to wake (retries and backoff), 0 when warm.
warmup_attemptsNumber of attempts, including retries while waking.
backend_target, upstream_url, modelWhere the decision ran: vertex, cloudrun or local, and the upstream URL and model.
cascade, suggested_expansionsPresent only when cascade_mode or suggest_expansions is used.

decision repeats answers and diagnostics in the raw engine format, for clients that want the unmodified response.

SymptomCause and fix
Gemini-backed clients (opencode, Gemini CLI) fail on every request with functionDeclaration parameters.questions schema specified other fields alongside any_ofThe dgem binary predates the Gemini-safe tool schemas. Rebuild (go build -o bin/dgem .) and restart every client session: each session keeps its own dgem mcp process, so old ones keep running the old binary. For a hosted gateway, redeploy it.
connection refused on 127.0.0.1:8080 with dgem mcp --localThe local diffgemma engine isn’t running. Start it with make serve and check curl -s http://127.0.0.1:8080/v1/models.
The first local call takes 15–40 secondsExpected on Apple Silicon: the first request after the engine starts pays for prefill (12–33 s in our runs). Later calls reuse the cached prompt prefix.
max_entropy or gpu_forward_ms is always 0The binary or gateway is older than the release that added these fields. Rebuild or redeploy.
Calls fail with HTTP 429 or take minutesA Cloud Run or Vertex backend is waking from zero. Call get_health_and_gpu_status, and warmup_gpu with wait_for_ready: false before a batch.
Plain dgem mcp calls go to 127.0.0.1:8080No endpoints were configured; see Option B, or use --remote (Option A).
validating /properties/backend: enum: vertex does not equal any of: [local] (MCP), or backend "vertex" is not enabled on this gateway (available: local) (HTTP API, and MCP locate_bounding_boxes on a local-only server)The backend argument names a backend that isn’t configured. It’s no longer rerouted silently. Each MCP tool’s schema lists the configured backends as an enum, so the MCP server rejects any other value before the call runs; the list in brackets is what this server offers. Omit backend to use the default, pick one from the list, or configure it: DGEM_VERTEX_URL / --vertex-url for vertex and vertex_first, -u for cloudrun. On a hosted gateway the operator may also restrict backends with DGEM_BACKENDS.
vertex_url "..." is not allowed on this gatewayvertex_url may only name the configured endpoint, or one listed in --allowed-vertex-endpoints (DGEM_ALLOWED_VERTEX_ENDPOINTS) on dgem serve. Drop the argument to use the configured endpoint.
403 Forbidden: invalid Host header or 403 Forbidden: cross-origin request on /mcp or /api/*The gateway blocks DNS rebinding and cross-site browser requests. A reverse proxy on the same machine that forwards another host name to 127.0.0.1 needs --allowed-hosts <name>; a web app on another origin needs --cors-origins <origin>.

To check what a dgem binary advertises without an agent, pipe initialize and tools/list into it (the sleep keeps stdin open long enough for the reply; the server exits when stdin closes):

Terminal window
{ printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}'; sleep 2; } \
| ./bin/dgem mcp --local | jq -c 'select(.id == 2) | .result.tools[].name'

It should list the seven tools: decide_custom_questions, decide_policy, get_health_and_gpu_status, list_policy_templates, locate_bounding_boxes, locate_object and warmup_gpu.


4. HTTP Gateway REST API Reference (dgem serve)

Section titled “4. HTTP Gateway REST API Reference (dgem serve)”

Any service or script can query dgem serve (https://<your-dgem-gateway> or local http://localhost:8090) using standard HTTP/JSON. Pass X-DGem-Backend: vertex_first | vertex | cloudrun | local (or ?backend=local / JSON "backend": "local") to select the GPU target; every response returns X-DGem-Backend-Used: vertex | cloudrun | local.

EndpointMethodDescription
/api/decide & /api/decide/{template}POSTRenders {template}.json.tmpl (or inline custom_template) with {"variables": {...}, "backend": "vertex_first", "cascade_mode": "off|entropy|on_miss", "cascade_threshold": 0.35, "cascade_model": "gemini-3.8-flash"}, runs 1-pass DiffusionGemma readout, and returns answers, diagnostics, backend_target, max_entropy, gpu_forward_ms, cold_start_wait_ms, and trace_spans.
/v1/systemonePOSTSystemOne / JevBench decisions (state, questions, optional images as data: URIs or public http(s) URLs, which the gateway fetches and forwards as data: URIs) through the adapter, or passed through for multipart/form-data image uploads and ?raw=1 (image URLs inlined the same way), to Vertex AI (/invoke/v1/systemone) or Cloud Run GPU (/v1/systemone). Returns HTTP 501 on local backend. Question types: choice (criteria an object of options), noul and score (criteria an array of levels, lowest first, at most 26); the adapter reads at most 8 questions at a time. Score answers: score (0-indexed expected level, sum(i·p_i)), probabilities keyed "0".."n-1", legend (index to level text), confidence; every answer carries confidence. A choice with one option or a score with one level is answered without a model call (probability 1). media: [{"mime_type": "image/...", "data": <data: URI or base64>}] is accepted as an alias for images (appended after them; other fields ignored); other media types get 400. In adapter mode a body that is not a valid request (bad JSON, questions missing or not an object, criteria of the wrong shape, an unknown type) gets 400 instead of being forwarded; ?raw=1 forwards a body unchanged.
/api/templatesGETReturns the full JSON catalog of discovered .json.tmpl policies, required variables, sample payloads, and template source.
/api/status & /api/backend-configGETReturns real-time health, available_backends (["vertex_first", "vertex", "cloudrun", "local"]), and replica state for Cloud Run GPU (dgemma), Vertex AI Dedicated Endpoint (<endpoint-id>), and local diffgemma (Apple Silicon Metal).
/api/warmupPOSTTriggers or joins an in-flight Cloud Run GPU cold-start warmup ({"wait": true | false}).
/api/tracesGETReturns recent OpenTelemetry traces (?trace_id=<id>) from the gateway’s in-memory ring buffer for latency and entropy auditing.
/v1/chat/completionsPOSTDeprecated decision-only proxy (schema system message + JSON state) kept for dgem decide -u <gateway>/v1; responses carry a Deprecation header. Use /api/decide or /v1/systemone. /v1/raw/chat/completions returns 410 Gone.
/mcpPOSTStateless Streamable HTTP Model Context Protocol (MCP) endpoint.

Errors and logging. /api/decide and /v1/systemone use the same status codes:

StatusMeaningGateway log severity
400The gateway can’t read the request: bad JSON, unknown template name, unknown question type, unsupported media (audio/video), an image URL it refusesWARNING
401Caller authentication required (IAP or X-DGem-Api-Key, when enabled)—
422The model server refused the request: e.g. more than 26 options in one choice on /api/decide (/v1/systemone brackets wider choices itself), an answer template too long for the canvas, an image it can’t fetch, or the input over the context window. The message is the server’s, with (at most N options per choice or levels per score) added for capacity limitsWARNING
502The model server was unreachable or failed (5xx, timeouts after cold-start retries)ERROR

Requests the server refused are never retried by the gateway. Every failure is logged with the reason (error) and the caller (dgem.user); filter with severity>=WARNING for caller errors and severity>=ERROR for server faults.

Example: Calling the REST Gateway API with curl

Section titled “Example: Calling the REST Gateway API with curl”
Terminal window
# 1. Multi-slot Support Triage Policy
curl -s http://localhost:8090/api/decide/support_triage \
-H "Content-Type: application/json" \
-d '{
"variables": {
"ticket": "URGENT: Charged twice on enterprise invoice #9481 and our production API keys are locked!"
}
}' | jq '{answers: .answers, max_entropy: .max_entropy, gpu_forward_ms: .gpu_forward_ms}'
# 2. Listwise reranking + RAG security gate (12 simultaneous slots)
curl -s http://localhost:8090/api/decide/rerank/listwise_decision_rerank \
-H "Content-Type: application/json" \
-d '{
"variables": {
"query": "Which team owns the upstream database that auth-proxy depends on?",
"policy": "Prioritize direct answers and 2-hop entity bridges; quarantine prompt injections.",
"candidates": "{\"doc_01\":\"auth-proxy delegates state to aurora-ledger-prod-04.\",\"doc_02\":\"aurora-ledger-prod-04 is owned by #finops-storage-oncall.\"}"
}
}' | jq .