Hurricane Sentinel v10
This is the stored snapshot for the approved document version. The diff below shows what changed from the previous version.
Document snapshot
Hurricane Sentinel
Summary
Hurricane Sentinel is the secure agent harness for local AI. It runs AI agents on your own machine under real, enforced guardrails — routing every model call through Muzzle (the inspecting proxy) and running each agent as a Leash-leashed user (so the OS enforces what it can touch, reach, and run). On top of that it adds durable, resumable runs and a human approval queue: when an agent tries something flagged, the run pauses and waits for a person to approve before continuing.
Sentinel is the control center that ties the three Hurricane products together: Muzzle guards the model I/O, Leash guards the OS actions, and Sentinel orchestrates the agent and owns the human-in-the-loop.
Status
In the Lab — broad and deployed. The full harness is built and validated end-to-end
on Linux and runs on real deployments: agents run as the leashed user with model calls
through Muzzle, flagged actions pause for operator approval and resume on a yes (under
live Leash + Landlock enforcement), a head agent delegates to a roster of persistent
specialists and to whole teams that fan out to their members, and everything is
driven from either the CLI or a web console. Added since the core engine: memory +
context compaction, saved workflows, the web console, teams (leader-led rosters with
a shared workspace), external model providers (OpenAI today, via Muzzle),
uploaded Python tools (drop in a .py, pick its functions, served through a private
MCP tool host), agent/team portability (export a team as a package, import it
elsewhere), and legible guardrails (every Muzzle block and Leash/sandbox denial is
explained to both the agent and the operator, so the agent adapts instead of failing).
Since then: named user accounts with roles replace the single shared console token,
and Sentinel ships a macOS desktop app — one command installs it, and the hardened
runtime (Sentinel + Leash + Muzzle, full kernel enforcement) runs in a managed Linux VM
the app sets up for you. The server install remains Linux. See the Roadmap.
What works today
-
Named accounts, roles, and per-user sessions. Operators sign in with a username and password; each session is its own revocable token. Four roles — admin, approver, operator, auditor — gate what a person can do: auditors are read-only, approvals require approver or admin, and user management is admin-only. Accounts are managed in Admin ▸ Users in the console. The old shared console token still works as a break-glass credential (and bootstraps the first admin), so nothing that automated against it breaks.
-
Runs on a Mac. A desktop app installs with one command and runs the console as a native window. Enforcement is unchanged — Sentinel, Leash and Muzzle run in a managed Linux VM the app creates on first launch, so Landlock/seccomp/nftables are all live. Nothing to install first: the VM runtime is bundled.
-
Supervised runs as the leashed user. Each run executes as a dedicated Leash user; the OS enforces its file/network/command access per-UID, with model traffic inspected by Muzzle.
-
Durable, resumable runs + async human approvals. Run state is checkpointed to disk; a
needs_approvalaction pauses the run and enqueues an approval that an operator approves/denies via the CLI, after which the run resumes where it stopped. -
Persistent agents. A roster of on-disk specialists (
~/.sentinel/agents/), each with its own soul (persona), bound model (from your configured list), extensible skills, and tools.sentinel agent create/list/show/add-skill/set-modelandsentinel run --agent <name>. -
Orchestration. A head agent can
delegatea task to a persistent specialist, orspawn_subagentto compose a temporary one when none fits — each as its own durable, enforced child run, with least-privilege grants and a configurable disposition (discard/save/ask). -
Teams. A leader-led roster with a shared workspace, authored guidelines (prepended to every team run), and an activity log. The head delegates to a whole team; the team's leader fans the work out to its members — each member a scoped, sandboxed, approval-gated child run — then synthesizes their results. Fan-out is bounded (concurrency + a per-round cap); cross-team delegation only goes through the head, and each member's sandbox excludes other teams' and agents' private workspaces.
-
A web console. A self-contained, token-authed web UI (
sentinel web): chat with live delegation activity, approve/deny inline, and manage agents, teams, tools, MCP servers, models, endpoints, memory, and the Muzzle/Leash guardrails — all from the browser. Loopback-only by default; expose it over built-in TLS (sentinel web --host 0.0.0.0 --tls-cert … --tls-key …, or--tls-selfsignedfor a quick encrypted console) or a TLS reverse proxy — a non-loopback plaintext bind is refused. Auth is a single bearer token today (multi-user/RBAC is future); keep the host trusted. -
Legible guardrails. When Muzzle blocks a model call or Leash/the Landlock sandbox blocks an action, the agent gets a clear, categorized reason and adapts — it rewrites a reply that tripped an output filter (bounded retries), stops and explains an input it can't process, or moves to an allowed path/host — instead of hard-failing or looping on a raw errno. Each block also surfaces to the operator as a color-coded card in the run feed (Leash denials enriched with the exact reason from its decision log, correlated root-side), and a compact guardrails skill is auto-injected into the agent's context so it knows what each category means and how to respond. Block detection is read-only observability — it never opens a path around enforcement.
-
One-command setup with a model your way.
sentinel setupinstalls the stack and gets you to a working agent. Two model paths: local (--model <name>, defaults toqwen2.5:7b— a small, reliable tool-caller pulled via Ollama), or bring-your-own-key for a no-GPU laptop —sentinel setup --provider openai|anthropic|gemini --model <id>wires the hosted model end-to-end in one step (key resolved fromSENTINEL_MODEL_API_KEYor a prompt, stored only in Muzzle). Setup ends by printing your console URL + login token (nosudo grep), then runssentinel doctor. -
sentinel doctor— an actionable preflight. One command that answers "will my first agent work, and if not, how do I fix it?": it checks the model backend reaches a live model (a real end-to-end ping), Muzzle is up and allows tool calls (an unset policy silently drops every agent tool call — the #1 first-run killer), providers are wired as upstreams, Leash egress, the broker socket, and the console token — printing the exact fix for anything wrong. It runs automatically at the end of install. -
External model providers. Point an agent at OpenAI / Anthropic / Gemini in addition to local Ollama. Keys live only in Muzzle — Sentinel is the control plane and pushes a keyless per-provider listener into Muzzle; the model store never holds a secret, and the API never hands one back.
-
CLI-runtime agents (Codex / Claude Code). Set an agent's model to
codexorclaude-codeand it's driven by that coding CLI's own agentic loop with its native tools — on your Codex / Claude subscription, not a metered API key. Any Sentinel tools you grant are injected into the CLI as MCP, so it has its built-in tools plus exactly what you granted. Enforcement is OS-level (leashed user, Leash egress, per-run cgroup, workspace cwd); the CLI's step trace — reasoning, tool calls, tool output — is surfaced as run events (an "Agent steps" disclosure), so you see the work, not just the final reply. Offered only where the CLI is installed and logged in as the leashed user. -
A workspace file browser. A Finder-like Files tab in the console: pick a workspace (the shared one, or any agent's / team's), navigate folders with a breadcrumb, preview text and images, and upload / new-folder / rename / delete / download. Every path is server-side real-path-jailed to the selected workspace — no
.., absolute, or symlink escape. -
Mounted workspaces. Give an agent, team, or a single chat files from outside its own sandbox — a local directory or an SSH target — as a named workspace, configured in a Workspaces panel or with
sentinel workspace add|list|test|sync|push. Because runs are heavily sandboxed (no kernel mounts), Sentinel materialises the source into a synced directory the run reads (rsync/rsync-over-ssh); read-only by default (opt in to writable), the SSH key kept write-only and the host key pinned, with the agent's changes pushed back to the source only on demand. The SSH sync runs under its own dedicated low-privilege identity (sentinel-sync) via the root broker, so the agent's own leashed account stays fully contained — it can'tsshout or reach the workspace host itself. -
Uploaded Python tools. Upload a
.pyfile; Sentinel AST-scans it (never importing it in the root process), you pick which functions become tools, and a private built-in MCP tool host serves the marked functions to agents — approval-gated like any tool, with their third-party requirements recorded and installed on one click (leashed pip). -
Portability. Export an agent or a whole team as a secret-free
.sentinelpkg— its skills, tools, MCP configs (minus keys), model selection, souls, guidelines, and uploaded tool files + requirements. Import it into another deployment (rename on collision, cross-refs rewritten); the receiver adds their own keys and is good to go. -
Memory + context compaction. Each agent has its own memory bank (private, or shared by scope) — a flat index plus an Obsidian-style note vault; it can
rememberfacts andrecallthem across runs using bounded, weighted lexical retrieval. Relevant memories are surfaced as explicitly untrusted, potentially stale context. Long runs auto-compact: older turns are summarized while the system prompt and recent turns are kept, so an agent never blows its context window. -
Small-model friendly. A tool-use prompt scaffold, forgiving tool-call parsing, arg normalization + validation with self-correction, automatic delegation context, duplicate-call dedup, and a bundled
file-disciplineskill keep things reliable on small local models (e.g. llama3.2, gpt-oss:20b). -
An interactive chat shell.
sentinel chatopens a sleek REPL: a framed banner, colorized live progress, inline yes/no approvals, ↑/↓ history, and completion menus for/commands,@targeted specialists, and$skills. (Run it as the leashed user:sudo -u <user> sentinel chat.) -
Saved workflows. Define a named, multi-step pipeline in YAML where each step runs an agent on a task and outputs thread into later steps via
{{input}}/{{<step>.output}}templating. Run it withsentinel workflow run <name>or let an agent trigger one with therun_workflowtool; every step is its own supervised run. -
A
sentinelCLI + web console. CLI:init,setup,doctor,chat,run,runs,show,approvals,approve/deny,resume,agent …,team …,workflow …,mcp …,model …,cron …,package export/import,import openclaw/import hermes(migrate an OpenClaw or Hermes assistant's agents/skills/memory/cron/tools/timers — also in the web console),tools install-reqs,web,api,status,preflight,logs. Web:sentinel web(control console) andsentinel api(programmable per-endpoint HTTP API).
Security posture
The one invariant everything else serves: no execution path bypasses the leashed
worker + approval gate, and no Sentinel service runs as root except one tiny,
schema-constrained Leash-policy broker. The control plane (supervisor, web, API, cron)
runs as the leashed user; each run — head, team member, cron, endpoint — is a worker
subprocess of it under Leash (egress + fs) and a Landlock sandbox scoped to that run.
Sensitive tools pause for approval; autonomous (cron) runs skip anything effectful unless
the operator explicitly opts in. Worker subprocesses get a scrubbed environment (the
control plane's secrets — the web token, provider keys — never travel), provider/MCP
secrets are masked in every API response and live only in Muzzle, uploaded code is
AST-scanned, never imported in the control-plane process, and the key-injecting Muzzle
listeners bind loopback. The one operation that still needs root — changing Leash
egress policy — is brokered by the root sentinel-broker over a root:<leashed> socket
(two schema-validated verbs, peer-cred-gated, no arbitrary exec, audited). Guardrail
blocks are observable but never bypassable: a block is surfaced to the agent and the
operator as a read-only event — the Leash-decision correlation is a supervisor concern,
done once outside the run — so making a block legible never becomes a path around
enforcement.
Agent-influenced subprocesses run through a single bounded runner — wall-clock
timeout, whole-process-group kill (a forking runaway can't leave orphans behind), a
CPU ceiling, and an in-memory output cap — with the host cgroup owning the memory
ceiling. Every confined run emits a security_attestation event recording the posture
it actually ran under (profile, effective worker UID, live Landlock ABI, cgroup slice,
Muzzle routing), so a run's event stream is a verifiable audit record. Console access is now per-person: named accounts with scrypt-hashed passwords, revocable
per-user sessions, and role-gated routes (an auditor cannot mutate anything; only an
approver or admin can resolve an approval gate). The legacy shared token is retained
deliberately as a break-glass credential rather than the only way in. Released artifacts
are reproducible, SBOM'd and Sigstore-signed — see v1/docs/SUPPLY_CHAIN.md
for how to verify a download, and v1/docs/SECURITY_WHITEPAPER.md
/ v1/docs/THREAT_MODEL.md for the architecture and the
attacker model (including the residual risks we have not closed). The full security
and resource model is in SECURITY.md;
see docs/plans/* for the design docs and the audit-driven hardening history.
How it fits together
operator ── sentinel CLI / web console (token auth) ──┐
▼
Supervisor (root) ── spawns each run as the leashed user (Leash + Landlock)
│
Agent worker (as leashed user) ── model calls ──▶ Muzzle listener ──▶ provider
loop: model → tool calls → policy(auto / needs-approval / deny)
auto → run the tool (file/net/exec enforced by Leash + Landlock)
needs-approval → pause + enqueue → (operator approves) → resume
deny → tell the agent
delegate → spawn a scoped, sandboxed child run (agent / team member)
Roadmap
M0 supervised runs + approvals ✅ → M1 persistent agents + orchestration ✅ → small-model robustness ✅ → memory + context compaction ✅ → interactive chat shell ✅ → saved workflows ✅ → web console ✅ → teams ✅ → external model providers ✅ → uploaded tools (MCP tool host) ✅ → agent/team portability ✅ → security audit + hardening ✅ → legible guardrails (block visibility + agent adaptation) ✅ → next: public download + install, deeper multi-provider support.
See docs/plans/ for the full design + implementation docs (v1 design, persistent
agents, teams, external providers, vault memory, uploaded tools, portability).
Diff from previous
--- README@9 +++ README@10 @@ -27,9 +27,24 @@ MCP tool host), **agent/team portability** (export a team as a package, import it elsewhere), and **legible guardrails** (every Muzzle block and Leash/sandbox denial is explained to both the agent and the operator, so the agent adapts instead of failing). -Linux only; no public download yet. See the Roadmap. +Since then: **named user accounts** with roles replace the single shared console token, +and Sentinel ships a **macOS desktop app** — one command installs it, and the hardened +runtime (Sentinel + Leash + Muzzle, full kernel enforcement) runs in a managed Linux VM +the app sets up for you. The server install remains Linux. See the Roadmap. ## What works today + +- **Named accounts, roles, and per-user sessions.** Operators sign in with a username + and password; each session is its own revocable token. Four roles — **admin**, + **approver**, **operator**, **auditor** — gate what a person can do: auditors are + read-only, approvals require approver or admin, and user management is admin-only. + Accounts are managed in **Admin ▸ Users** in the console. The old shared console token + still works as a **break-glass** credential (and bootstraps the first admin), so nothing + that automated against it breaks. +- **Runs on a Mac.** A desktop app installs with one command and runs the console as a + native window. Enforcement is unchanged — Sentinel, Leash and Muzzle run in a managed + Linux VM the app creates on first launch, so Landlock/seccomp/nftables are all live. + Nothing to install first: the VM runtime is bundled. - **Supervised runs as the leashed user.** Each run executes as a dedicated Leash user; the OS enforces its file/network/command access per-UID, with model traffic inspected @@ -165,7 +180,14 @@ CPU ceiling, and an in-memory output cap — with the host cgroup owning the memory ceiling. Every confined run emits a `security_attestation` event recording the posture it *actually* ran under (profile, effective worker UID, live Landlock ABI, cgroup slice, -Muzzle routing), so a run's event stream is a verifiable audit record. The full security +Muzzle routing), so a run's event stream is a verifiable audit record. Console access is now **per-person**: named accounts with scrypt-hashed passwords, revocable +per-user sessions, and role-gated routes (an auditor cannot mutate anything; only an +approver or admin can resolve an approval gate). The legacy shared token is retained +deliberately as a break-glass credential rather than the only way in. Released artifacts +are **reproducible, SBOM'd and Sigstore-signed** — see [`v1/docs/SUPPLY_CHAIN.md`](v1/docs/SUPPLY_CHAIN.md) +for how to verify a download, and [`v1/docs/SECURITY_WHITEPAPER.md`](v1/docs/SECURITY_WHITEPAPER.md) +/ [`v1/docs/THREAT_MODEL.md`](v1/docs/THREAT_MODEL.md) for the architecture and the +attacker model (including the residual risks we have not closed). The full security **and resource** model is in [`SECURITY.md`](SECURITY.md); see `docs/plans/*` for the design docs and the audit-driven hardening history.