Open source. Limited beta. Local stdio only. Version 0.4.0b1 on PyPI.
Your agent said ‘done.’ Fourgate checks whether it actually happened.
Independent outcome verification for consequential AI-agent actions.
python -m pip install --pre "fourgate==0.4.0b1"fourgate demo- 1. Tool says done: Fourgate only checks results the tool reported as success; an error result is recorded as UNKNOWN (not_success_result).
- 2. Extract contracted fields: It extracts only the contract-approved fields, such as the record ID; if one is missing, the result is UNKNOWN.
- 3. Independent read-back: A separate read-only GET asks the system of record for the record: missing or different is FAIL, unreachable is UNKNOWN.
- 4. Verdict: Only a confirmed match is PASS. UNKNOWN is never counted as PASS, and it fails open: the call goes through unchanged.
A tool saying “success” is not the same as the system changing.
An agent that reads a tool result without isError has no protocol-level signal that the call failed. Fourgate checks the outcome itself: after a protected tool reports success, it reads the system of record back and records one of three results. No LLM decides.
Pick a connector and a mode. See what really happened.
Every value below comes from one recorded run of fourgate demo --pace 0 (fourgate 0.4.0b1): a simulated connector, with a local file standing in for the system of record. Only the five recorded combinations can be selected.
Or jump to a recorded scene
S2
Fourgate enforce: broken connector
The agent is told the write did not land, before it can report success.
What the agent receives
- Agent receives, first:[FOURGATE] outcome_failed (reason: record_missing, recovery: stop)
- then the original:"Created ISSUE-001"
- isError=false
System of record
0 issues saved
Outcome log
FAIL record_missing (mode: enforce)
Raw terminal output for S2
FOURGATE DEMO - local only: no API keys, no network, nothing leaves this machine Simulated connector; a local file stands in for the system of record. An agent asks the demo-crm connector to create_issue "Q3 renewal follow-up". Each scene is a real MCP session; scenes S2-S5 run through a real `fourgate guard` process, which reads the system of record back after the connector reports success. [2/5] S2 Fourgate enforce: broken connector Same broken connector, now behind `fourgate guard --mode enforce`. Agent receives, first: [FOURGATE] outcome_failed (reason: record_missing, recovery: stop) then the original: "Created ISSUE-001" isError=false System of record: 0 issues saved Outcome log: FAIL record_missing (mode: enforce) -> The agent is told the write did not land, before it can report success.
A local guard, an independent read-back, a local record.
fourgate guard sits on the local stdio path between your agent and your MCP server. When a protected tool reports success, it extracts only the contracted fields, and a local verifier reads the record back with a separate, read-only credential.
tools/call
unchanged
its own write
read back by the verifier: independent read-only GET
structure only
local HTML
Wrap the command. Leave the server alone.
Fourgate goes in front of the command your MCP client already runs. Start in shadow mode: verdicts are recorded and the agent sees nothing different.
{ "mcpServers": { "my-server": { "command": "python", "args": ["your_server.py"] } }}Same thing as a shell command
python your_server.py
The file name and shape depend on your MCP client; only the command changes. runtime.json is the contract file fourgate init writes.
Six commands, in order.
Each step shows the real command. Where we captured a run, you see its exact output; where we did not, you see what the README says to expect.
See it work: local, simulated, no keys, no network.
fourgate demo --pace 0FOURGATE DEMO - local only: no API keys, no network, nothing leaves this machineSimulated connector; a local file stands in for the system of record.An agent asks the demo-crm connector to create_issue "Q3 renewal follow-up".Each scene is a real MCP session; scenes S2-S5 run through a real `fourgate guard` process,which reads the system of record back after the connector reports success.[1/5] S1 Without Fourgate: broken connector, called directly The connector reports success but never saves the issue. No Fourgate in the path. Agent receives: "Created ISSUE-001" (isError=false) System of record: 0 issues saved Outcome log: no record (Fourgate is not in the path) -> The agent believes the issue exists. It does not.[2/5] S2 Fourgate enforce: broken connector Same broken connector, now behind `fourgate guard --mode enforce`. Agent receives, first: [FOURGATE] outcome_failed (reason: record_missing, recovery: stop) then the original: "Created ISSUE-001" isError=false System of record: 0 issues saved Outcome log: FAIL record_missing (mode: enforce) -> The agent is told the write did not land, before it can report success.[3/5] S3 Fourgate enforce: healthy connector A healthy connector that really saves the issue, behind `fourgate guard --mode enforce`. Agent receives: "Created ISSUE-001" (isError=false) The response is identical to scene S1: no [FOURGATE] verdict System of record: 1 issue saved Outcome log: PASS postcondition_satisfied (mode: enforce) -> A real success passes through untouched.[4/5] S4 Fourgate shadow: broken connector The broken connector behind `fourgate guard --mode shadow` (the default mode). Agent receives: "Created ISSUE-001" (isError=false) The response is identical to scene S1: no [FOURGATE] verdict System of record: 0 issues saved Outcome log: FAIL record_missing (mode: shadow) -> The agent is unaffected; you still learn the write did not land.[5/5] S5 Fourgate enforce: broken connector, system of record unreachable The broken connector in enforce mode, but the read-back cannot reach the system of record. Agent receives: "Created ISSUE-001" (isError=false) The response is identical to scene S1: no [FOURGATE] verdict System of record: 0 issues saved Outcome log: UNKNOWN verifier_error (mode: enforce) -> Fourgate could not confirm either way: recorded UNKNOWN, never PASS, and the call is not blocked.Summary Totals (from fourgate summary): PASS 1 / FAIL 2 / UNKNOWN 1 Outcome log: ./fourgate-demo/demo-outcomes.jsonl Summary page: ./fourgate-demo/fourgate-demo-summary.htmlSelf-check: every scene behaved as narrated.
Built to be checked, not trusted.
Runs on your machine
A laptop, a server or your CI. There is no Fourgate cloud service, account, database or telemetry.
No code changes
Wrap the MCP server's launch command with fourgate guard. Your agent and server code stay as they are; you add a short contract per protected tool.
Any HTTP API read-back
If the system of record exposes a GET endpoint for the written record, Fourgate can check it, with a Bearer token, a custom header or Basic auth.
Shadow first, byte-identical
In shadow mode, the default, your agent receives exactly the same bytes it would without Fourgate. Verdicts are only recorded.
UNKNOWN is never PASS
Timeouts, auth errors and Fourgate's own faults are UNKNOWN and fail open. Nothing uncertain is reported as success.
Open source
MIT licensed. Read the code, install from PyPI, and check release files against the SHA-256 digests GitHub lists.
What we have tested, and what we have not seen yet.
Operator-run tests against official vendor MCP servers, as of 2026-10-01. Vendors are not named. Small numbers, stated as they are.
- 4
- official vendor MCP servers tested, run locally against the vendors' live APIs using disposable test accounts or deliberately invalid credentials.
- 3 of 4
- surfaced API failures as successful tool results without MCP isError. Each was reproduced at least twice and reported upstream.
- Exercised
- Hosted authoritative read-back: a real hosted write verified PASS by an independent HTTPS read-back, with FAIL and UNKNOWN controls behaving as specified.
- Exercised
- Real-agent shadow calls: a real agent client made 2 protected send calls through the runtime wrap in shadow mode against a hosted MCP server. Both recorded PASS.
- 0not observed yet
- naturally occurring read-back-proven silent-success incidents observed so far: no write reported as done whose record turned out missing or wrong.
The failures found so far are error-reporting bugs, which Fourgate reports as UNKNOWN / success_without_record_id rather than PASS. One hosted integration does not establish production reliability, and two shadow calls are a smoke test, not production traffic. The full field record is in the README.
Free to run. Paid help to get it right.
Open Source
Free
MIT licensed. All six commands. Community support on GitHub.
Fourgate Founding Pilot
$300 one-time
Founder-assisted setup, outcome checks for up to three write tools in your CI, and a fix report with evidence.
Enterprise
Contact us
More workflows or tools than the pilot scope.
Questions a careful buyer asks.
Check up to three write tools, in your CI, with us.
Pick 1–3 state-changing tools that matter. We write the checks with you, run them in your CI against a test account you create, and send a fix report with evidence.