Skip to content

Latest commit

 

History

History
86 lines (74 loc) · 4.84 KB

File metadata and controls

86 lines (74 loc) · 4.84 KB

ORCA API — frontend integration contract

Base URL (dev): http://localhost:8000 · WebSocket: ws://localhost:8000/ws CORS is wide open — a Stitch HTML export opened from a folder can call this directly.

Start the server: uvicorn orca.api:app --reload --port 8000 (deps: pip install fastapi 'uvicorn[standard]' pydantic websockets)

The one payload shape: Event

Every REST list and every WebSocket message is this JSON object (fields may be null when not applicable):

{
  "event_id": "8d3f…",
  "trace_id": "T-4a1b2c3d",
  "parent_id": "77aa…",
  "agent_id": "procurement-01",
  "framework": "orca",
  "team": "supply-chain",
  "timestamp": "2026-07-09T12:00:01.123456+00:00",
  "event_type": "tool_call",
  "status": "blocked",
  "task": "Export vendor list to external address",
  "action": {"tool": "vendor_db.export", "risk_level": "critical", "reversible": true},
  "data_provenance": {"sources": ["doc:pid_042.pdf"], "tainted": true, "taint_source": "doc:pid_042.pdf"},
  "cost": {"input_tokens": 900, "output_tokens": 60, "usd": 0.010},
  "policy": {"verdict": "block", "rule_id": "tainted-input-dangerous-action", "tags": ["OWASP-LLM01"]},
  "review": null,
  "prev_hash": "…64 hex chars…",
  "hash": "…64 hex chars…"
}
  • event_type: agent_start | tool_call | handoff | decision | output | error | escalation | agent_end
  • status: ok | blocked | escalated | flagged | failed
  • output events may carry content (the produced text) and review ({confidence, judge_verdict} from the Quality Gate) — status: "flagged" means the judge disagreed and a human should look
  • decision events carry approval ({decision, reviewed_by}) — the audit answer to "who approved this?"
  • Judge config (server env): JUDGE_PROVIDER=mock (default) or llm with LLM_ENDPOINT, LLM_API_KEY, LLM_DEPLOYMENT
  • policy.verdict: allow | block | escalate; policy.tags carries threat labels like OWASP-LLM01
  • Lineage: follow parent_idevent_id (works across agents and sub-agents)

Endpoints

Endpoint Returns Powers
GET /agents registered agents + per-task tool allowlists agent cards
GET /events?trace_id=&agent_id=&limit= Event list (chronological) feed, replay, per-agent filter
GET /traces one summary row per workflow run (events, usd, blocked, escalated, agents) run picker, replay entry point
GET /lineage?trace_id= {from, to, trace_id, task, timestamp} agent-level edges the DAG (react-flow)
GET /costs {per_agent, per_team, per_task} USD roll-ups cost attribution charts
GET /flagged Events with status blocked/escalated/flagged/failed alerts panel
GET /trace/{trace_id} {events, layers, agents} — everything for one run; layers = event_ids grouped by call-tree depth replay view + "one layer at a time" filter
GET /traceback/{event_id} the event's ancestry, root first "trace to root cause" click
GET /blast/{event_id} all events triggered downstream blast-radius highlight on the DAG
GET /verify {chain_ok: bool, first_bad_event: id|null} "audit chain verified ✓" badge
GET /approvals frozen Events awaiting a human — escalated tool calls AND judge-flagged outputs (action is null for outputs) approval modal list
GET /report?trace_id= compliance report as JSON (omit trace_id for all runs) compliance view
GET /report.md?trace_id= same report as downloadable markdown "download compliance report" button
POST /approvals/{event_id} body {"decision": "approve"|"give_up"|"try_another", "reviewed_by": "name"} {ok: bool} — releases the frozen agent; reviewer lands in the audit chain approval modal buttons
POST /demo/rogue launches a runaway + silent agent; tripwires fire live demo trigger button
WS /ws every new Event as it happens everything live

Tripwire alerts arrive as escalation events with status: "flagged" and policy.rule_id of tripwire-token-budget (cumulative per trace), tripwire-loop (same tool N× consecutively), or tripwire-silent-failure (agent started, then silence). Cross-framework: events from guarded LangGraph tools carry framework: "langgraph" and are enforced (blocked calls never execute) — see orca/adapters.py.

Recommended wiring (same pattern as Allen's useAgentEvents hook)

  1. On page load, snapshot via REST (/agents, /events, /costs, /flagged).
  2. Open the WebSocket; every message is one Event — append to the feed, add cost.usd to that agent's total, and if status is blocked/escalated, raise the alert UI.
  3. Send any text on the socket every ~15s as a keep-alive.

The demo scenario re-runs every 45s, so there's always live data. A blocked event with policy.tags containing OWASP-LLM01 is the demo moment — give it the loudest visual treatment.