SphinxGo

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0

README

Sphinx · Agent HITL Control Plane

Framework-agnostic, self-hosted, open-source human-in-the-loop approval control plane for agent workflows.

Sphinx is the missing middle layer between agent frameworks and the humans who must supervise them. It sits between LangGraph / OpenAI SDK / CrewAI / any MCP-capable agent and the reviewer, and gives you the things every framework leaves out:

  • Unified approval entry point — one web console + one approval queue for every framework, instead of one bespoke UI per framework.
  • Approval SLA with auto-degradation — timeouts that escalate, auto-approve or auto-reject per policy, so "human-in-the-loop" does not decay into "blind clicking OK".
  • Decision log & feedback loop — records the delta between what the agent proposed and what a human decided, and feeds governance metrics: escalation rate, error escape rate, reviewer agreement, correction rate, SLA compliance, decision latency.
  • Full decision capture — intercepts every tool call, LLM inference and state change into a tamper-evident trail (SHA3-256 hash chain + Ed25519 signatures), verifiable anytime via GET /api/capture/verify.
  • MCP-native — every capability is exposed as MCP tools, aligned with the 2026 protocol convergence direction. Any MCP-capable agent can request approval without new SDK code.
  • Single self-contained binary — the REST API, WebSocket live-events, MCP server and web console run in one Go process (CGO-free, SQLite embedded).

Repository layout

.
├── cmd/sphinx/            entrypoint — REST :8001, MCP :8100, web console, policy engine
├── internal/
│   ├── api/               REST + WebSocket handlers, CORS / logging middleware
│   ├── core/              policy engine, metrics, event bus, delta diffing, capture chain, store
│   ├── db/                SQLite bootstrap (modernc.org/sqlite, CGO-free)
│   ├── mcp/               MCP streamable-HTTP server exposing sphinx_* tools
│   ├── models/            domain types + DTOs (wire-compatible with the REST contract)
│   ├── seed/              default policies + realistic demo data + a capture chain
│   ├── config/            SPHINX_* environment configuration
│   └── web/               embedded web console (React build compiled into the binary)
├── web/                   React + Vite + TS console: Queue / Decisions / Metrics / Policies
├── docker/                multi-stage Dockerfile (web → go → minimal runtime)
├── docker-compose.yml     one-command stack: REST+MCP+console on :8001 / :8100
└── docs/                  full documentation set (see below)

Documentation

doc contents
docs/API.md full REST + WebSocket reference with JSON examples
docs/MCP.md MCP tools, config snippets, transport options
docs/SDK.md integrate your agents (Go) — REST/MCP lifecycle + capture trail
docs/USER_GUIDE.md install, run, configure, deploy — the operating manual
docs/ARCHITECTURE.md component breakdown, key flows, capture chain internals

Quick start

Option A — Docker Compose
docker compose up --build
Service URL
Web console http://localhost:8001
REST API http://localhost:8001/api
MCP endpoint http://localhost:8100/mcp
Live events (WS) ws://localhost:8001/api/ws

The stack boots with default policies and 28 rows of realistic demo data, so every page is populated immediately.

Option B — local development
go run ./cmd/sphinx                # or: make run
# with demo data and a fresh database
SPHINX_SEED_DEMO_DATA=1 SPHINX_DATABASE_URL=sqlite:////tmp/sphinx.db go run ./cmd/sphinx

The web console is embedded in the binary, so no separate frontend server is needed. During frontend development use Vite's dev server instead:

cd web && npm install && npm run dev

Vite runs on :5173 and proxies /api to :8001 and /mcp to :8100.


Core concepts

Approval requests

An agent submits an action_payload for approval with a risk_level (low/medium/high/critical). Sphinx picks a matching policy, stamps an SLA deadline, and the request lands in the queue.

  • low risk under a low-risk-auto policy → instant auto-approve (humans only see things that matter).
  • otherwise it stays pending until a human approves/rejects, the agent cancels, or the SLA fires.
Policies & SLA auto-degradation

A background engine scans pending requests every second. When a request exceeds its timeout_seconds, the policy's on_timeout action runs:

on_timeout effect
escalate marks the request escalated (stays pending, shows in console)
auto_approve auto-approves with the agent's payload
auto_reject auto-rejects

This is the anti-fatigue layer: if nobody looks at a ticket in time, the policy decides deterministically instead of leaving the agent stuck forever.

Decision log & governance metrics

Every decision is written to the decision log with:

  • agent_decision — what the model proposed
  • human_decision — what actually happened (may be amended)
  • delta — a path-level diff of the two payloads (add / remove / replace)
  • agreement — did the human confirm the agent unchanged?
  • sourcehuman_review / policy_timeout / auto_policy / agent_feedback

The metrics endpoint turns that log into governance KPIs:

metric definition
escalation_rate escalated requests / total created
timeout_rate SLA auto-decided / decided
correction_rate human reviews that changed the payload / human reviews
reviewer_agreement human reviews confirming the agent unchanged
error_escape_rate approved actions reported with a negative outcome / approved with feedback
sla_compliance_rate decisions reached before the SLA deadline / decided
latency avg / p50 / p95 human review decision latency
Live events

Mutations publish to an in-process event bus; the WebSocket endpoint /api/ws fans them out (requests, decisions, policies, capture topics). The console uses this for instant badge updates (and falls back to polling).


Using Sphinx from your agents

Via MCP (any framework)
// mcp config
{
  "mcpServers": {
    "sphinx": { "url": "http://localhost:8100/mcp" }
  }
}

Tools: sphinx_request_approval, sphinx_get_status, sphinx_wait_for_decision, sphinx_get_decision, sphinx_submit_feedback, sphinx_list_policies.

Via plain REST
# agent proposes a risky action
curl -X POST http://localhost:8001/api/requests \
  -H 'Content-Type: application/json' \
  -d '{"agent_id":"refund-agent","title":"Approve refund of $980 for order ORD-77241",
       "action_payload":{"action":"refund","order_id":"ORD-77241","amount_usd":980},
       "risk_level":"medium"}'
# → {"id":"...","ref":"SPH-1A2B3C","status":"pending", ...}

# agent waits (polls status)
curl http://localhost:8001/api/requests/SPH-1A2B3C
# → {"status":"approved","decision_payload":{"action":"refund","order_id":"ORD-77241","amount_usd":980}, ...}

# agent executes with the (possibly human-amended) payload, then reports the outcome
curl -X POST http://localhost:8001/api/requests/<id>/feedback \
  -H 'Content-Type: application/json' \
  -d '{"outcome":"success","note":"refund completed"}'

Capturing every agent step

Stream every tool call, LLM inference and state change into a tamper-evident trail — each step is hashed (SHA3-256), chained via prev_hash and Ed25519-signed, and can be re-verified at any time:

curl -X POST http://localhost:8001/api/capture \
  -H 'Content-Type: application/json' \
  -d '{"agent_id":"refund-agent","session_id":"sess-1","events":[
        {"event_type":"tool_call","event_name":"lookup_order",
         "input_payload":{"order_id":"ORD-88231"},
         "output_payload":{"order":{"amount_usd":1240}},
         "metadata":{"tool":"order_db","duration_ms":41},"status":"ok"}]}'

# later: verify the trail is untampered
curl "http://localhost:8001/api/capture/verify?agent_id=refund-agent&session_id=sess-1"
# → {"valid":true,"checked":1,"chains":1,"errors":[]}

Capture is fail-open: if Sphinx is unreachable, events are dropped with a log line and the agent's main path never blocks. See docs/API.md for the full capture endpoints.

Testing

make test        # go vet + go test ./... + frontend vitest

The Go suite covers the service layer, delta diffing, metrics math, the SLA scheduler, the full REST surface, WebSocket live events, MCP tools over a real streamable-HTTP server, capture-chain integrity and seed data. The frontend suite covers the queue, decisions, metrics, policies pages and live-update hooks.

Configuration

All settings are read from SPHINX_* environment variables (see internal/config/config.go):

variable default purpose
SPHINX_DATABASE_URL sqlite:///./sphinx.db SQLite URL (WAL mode, CGO-free)
SPHINX_API_PORT 8001 REST API + WS + console port
SPHINX_MCP_PORT 8100 MCP streamable HTTP port
SPHINX_SCHEDULER_INTERVAL_SECONDS 1.0 SLA engine tick interval
SPHINX_DEFAULT_POLICY_SEED true seed the 4 default policies at startup
SPHINX_SEED_DEMO_DATA false seed 28 demo requests at startup
SPHINX_CORS_ORIGINS * CORS allow-list
SPHINX_LOG_LEVEL info log level

License

Open source. Built for the LANDSLIDE human-computer collaboration initiative.

Directories

Path Synopsis
cmd
sphinx command
Command sphinx is the Sphinx HITL control plane server.
Command sphinx is the Sphinx HITL control plane server.
internal
api
Package api exposes the Sphinx REST API, WebSocket endpoint, MCP server and embedded web console over a single HTTP server.
Package api exposes the Sphinx REST API, WebSocket endpoint, MCP server and embedded web console over a single HTTP server.
config
Package config loads Sphinx settings from SPHINX_* environment variables.
Package config loads Sphinx settings from SPHINX_* environment variables.
core
Package core contains the business logic of the Sphinx control plane: event bus, delta diffing, tamper-evident capture chain, SLA policy engine, governance metrics and the persistence store.
Package core contains the business logic of the Sphinx control plane: event bus, delta diffing, tamper-evident capture chain, SLA policy engine, governance metrics and the persistence store.
db
Package db opens and migrates the SQLite database.
Package db opens and migrates the SQLite database.
mcp
Package mcp exposes the Sphinx HITL control plane as MCP tools over streamable HTTP.
Package mcp exposes the Sphinx HITL control plane as MCP tools over streamable HTTP.
models
Package models defines the core domain types of the Sphinx HITL control plane.
Package models defines the core domain types of the Sphinx HITL control plane.
seed
Package seed populates default policies, realistic demo requests and a demo capture chain so the console dashboard is populated on first boot.
Package seed populates default policies, realistic demo requests and a demo capture chain so the console dashboard is populated on first boot.
web
Package web embeds the compiled web console and serves it with SPA fallback.
Package web embeds the compiled web console and serves it with SPA fallback.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL