scan_dependencies lookup_advisories assess_blast_radius open_pull_request · gated
TrueForge agent harness · MCP tools · Daytona sandbox

SENTINEL

Anautonomoussupply-chainCVEstriketeam,withroomtobreathe.

It reads your dependency tree, triages every advisory against the versions you actually ship, works out how risky each fix is, prepares the patch — and then stops and asks a human before it opens the pull request.

8-stage pipeline7 MCP toolsapproval-gated writesOSV live data17 WebMCP tools
sentinel — triage owner/repo
01 Inventorylockfile resolved
02 Triage14 advisories → 3 match
03 Delegate3 subagents spawned
04 Assess1 major · 2 patch
05 Planhighest fix version
06 Patchranges preserved
07 Verify93/93 in sandbox
08 Proposewaiting for a human
sentinel ▸
approval required: open_pull_request · destructive
Constellationreading…
tools in page—
tools over MCP—
protocol—
round trip—

Same tools, two doors: document.modelContext for an agent inside your browser, POST /api/mcp for one outside it.

The last row is the point of the project. The pause is real: the turn ends, the console shows the full tool call and its arguments, and nothing happens until a person clicks.

The problem

Nobody has an afternoon.

A dependency advisory lands. Someone has to work out whether this repository is genuinely affected, whether the fix is a one-line bump or a breaking change, whether the test suite survives it, and then write the pull request. That is an afternoon per advisory, and most teams do it late — or not at all.

Every software team on earth has this backlog. The work is not knowledge work any more; it is repetition at scale, and repetition is exactly what an agent should be doing. SENTINEL is that agent. Everything up to the pull request is autonomous. The pull request itself is not — that is the irreversible step, and it stops there and asks.

What SENTINEL does

Eight stages. The last one is yours.

01scan_dependencies

Inventory

Reads package.json and the lockfile, resolving real installed versions rather than declared ranges.

02lookup_advisories

Triage

Queries the GitHub Advisory Database (OSV fallback) and keeps only advisories whose version range actually matches.

03subagents

Delegate

Spawns one subagent per affected package, each with a clean context window — ten CVEs do not share (and exhaust) one.

04assess_blast_radius

Assess

Works out whether each upgrade is a patch, minor or major bump, and how widely the package is imported.

05summarise_triage

Plan

Collapses findings into one safe target version per package — the highest fix version, so no advisory is left open.

06propose_patch

Patch

Generates the updated package.json, preserving the project's existing range operators.

07sandbox

Verify

Installs and runs the test suite in an isolated Daytona sandbox.

08open_pull_request

Propose

Opens the pull request. Pauses. Waits for a human.

Why the harness does the work

We do not reimplement any part of the agent loop.

No while (toolCalls), no retry logic, no context compaction, no approval state machine. Those all exist in TrueForge. What SENTINEL owns is the two things the harness deliberately leaves to you: a tool server — the domain expertise, remote MCP over streamable HTTP — and two front ends driving the same core.

┌──────────────────┐        ┌──────────────────┐
│  Terminal client │        │    Web client    │      ← this console
│  (src/cli)       │        │  (src/web)       │
└────────┬─────────┘        └────────┬─────────┘
         │                            │
         │   both speak the SAME core │
         └─────────────┬──────────────┘
                       ▼
         ┌───────────────────────────────┐
         │  src/harness  (our thin layer) │
         │  provision · runner · events   │
         └───────────────┬───────────────┘
                         │  @truefoundry/trueforge-sdk (HTTP)
                         ▼
         ╔═══════════════════════════════╗
         ║   TrueForge harness (theirs)  ║
         ║   agent loop · context mgmt   ║
         ║   subagents · approvals       ║
         ║   session state · sandbox     ║
         ╚═══╤═══════════╤═══════════╤═══╝
             │           │           │
       model │       MCP │   sandbox │
             ▼           ▼           ▼
        OpenAI /    src/mcp      Daytona
        Anthropic  (our tool     (isolated
        / Gemini    server)       exec)
The 7 MCP tools

Safety declared on the tool, once.

Seven domain tools over remote streamable HTTP, bearer-authenticated. The classification lives next to the implementation, and both front ends inherit it automatically. A mis-tagged tool fails closed.

ToolAnnotationApproval
scan_dependenciesreadOnlyHintno
lookup_advisoriesreadOnlyHintno
assess_blast_radiusreadOnlyHintno
summarise_triagereadOnlyHintno
propose_patchreadOnlyHintno — writes only inside the sandbox
open_pull_requestdestructiveHintapproval required
merge_pull_requestdestructiveHintapproval required
Control and safety

Structural, not a prompt the model can talk its way out of.

✓ The approval policy is declared on the tool, once

TrueForge resolves its @read-only / @write / @destructive approval selectors from MCP tool annotations. The classification lives next to the implementation, and both front ends inherit it automatically.

✓ Defence in depth on the irreversible path

The agent spec gates @destructive and names both tools literally. Destructive handlers check the kill switch before any network call. GitHubClient re-checks it at the point of mutation. Branch names are generated by us — the model never supplies a ref.

✓ Failing safe

Denial is the default everywhere: empty input, EOF, Escape, and unparseable answers all deny. The web API only accepts approvals for tool calls the harness actually raised.

✓ Keeping secrets out

Keys live only in .env, git-ignored, read at one place. The browser never talks to the harness or a provider directly — everything is proxied. Two-layer redaction scrubs every log line, tool result and SSE frame.

Degradation strategy

Each capability degrades independently.

Model key

Hard fail at provision, with the exact env var named.

DAYTONA_API_KEY

Sandbox disabled; patches reported unverified rather than silently claimed.

GITHUB_TOKEN

GitHub tools return a typed “not configured” error; scanning and triage still work.

Harness not running

Clients print the npx @truefoundry/trueforge command instead of a stack trace.

Included: the WebMCP OMNI-LAB

Five in-browser laboratories. Seventeen registered tools.

A client-side WebMCP demonstration registered via the W3C/OpenAI document.modelContext.registerTool(...) standard — the escrow and forensic modules use real SHA-256 / HMAC-SHA-256 digests.

BreachLab

AST triage

Static analysis that traces taint from source to sink, scores the threat, and synthesises a hotpatch diff.

BioSynth

3D protein CAD

Crambin crystallographic coordinates, point mutagenesis with ΔΔG and steric clashes, binding-pocket discovery.

ChronoForensic

OSINT

Multi-angle sensor streams, acoustic triangulation, and a sealed SHA-256 forensic dossier.

MetaLoop

swarm debugger

Agent execution trace trees, synthetic tool injection, and cognitive-drift compensation.

ZK Escrow

arbiter

Real SHA-256 / HMAC-SHA-256 digests, milestone-gated escrow release, zero-knowledge deliverable proofs.

The agent bridge

Use SENTINEL from ChatGPT, Claude or your own agent.

The same seventeen OMNI-LAB tools and the same triage stages are published twice: on document.modelContext for an agent driving a tab — WebMCP, the W3C surface ChatGPT's built-in browser and ChatGPT Sites speak since August 2026 — and over POST /api/mcp for an agent outside it, as stateless Streamable HTTP per MCP 2026-07-28, with the older initialize handshake still answered for clients that need it.

In the browser

Tools registered on the page

Open this site in the ChatGPT desktop app's built-in browser and ask it to triage a repository — the registered tools are surfaced by the browser, with their readOnlyHint annotations intact. In Chrome the API is behind a public origin trial; set NEXT_PUBLIC_WEBMCP_ORIGIN_TRIAL to opt this host in. Where no native surface exists, the console says “in-page only” rather than pretending.

document.modelContexttitle · inputSchema · annotationsAbortSignal unregistrationtoolchange events
Outside the browser

One remote MCP endpoint

Paste https://your-host/api/mcp into ChatGPT's developer-mode connector, claude mcp add, Cursor's mcp.json, Gemini CLI or any MCP client. No key needed for the read-only tools; set SENTINEL_MCP_TOKEN to require a bearer token for calls, and SENTINEL_ALLOW_REMOTE_WRITES=true before a write tool exists at all.

server/discoverMcp-Method · Mcp-Name headersttlMs · cacheScopelegacy initialize
Live check

Nothing has been probed yet. The check is read-only: it calls server/discover and tools/list, invokes one safe tool through document.modelContext, and confirms that the destructive tools refuse. It never opens a pull request.

That check is not a demo counter: it reads the tools back through the model context, invokes one, and asks the destructive tool to refuse. The Bridge station does the same from inside the console, with a playground for raw JSON-RPC.

FAQ

The questions that matter.

Will it open a pull request without asking me?

No. open_pull_request and merge_pull_request are annotated destructiveHint, so the harness raises a real approval gate. The turn ends and waits. Denial is the default for every input it cannot interpret.

Do I need an API key to try it?

No. A scripted model endpoint ships with the project, so the whole path — real advisory data, real tools, real gate — runs without spending anything.

Which ecosystems does it cover?

Node and npm: it reads package.json plus the lockfile and triages against the GitHub Advisory Database, with OSV as a fallback.

What happens without a sandbox key?

The agent cannot execute or test a patch, and is explicitly instructed to report every patch as unverified. It never guesses that a fix works.

Can I run it fully read-only?

Yes — set SENTINEL_ALLOW_REMOTE_WRITES=false. Destructive tools then refuse before any network call, regardless of what the model or the approval UI says.

Could a demo recording leak a token?

Not through SENTINEL. Redaction runs in two layers — exact registered values plus ten credential shapes — scrubbed from every log line, tool result and SSE frame.

The pause is the product

Run the strike team.

No API key needed to see the whole path — real advisory data, real tools, real approval gate — straight from the browser.