Triadr
Allows auditing pull requests by reviewing diff surface, sensitive paths, tests, and CI, generating a 0-100 risk score, and writing the verdict as a commit status check.
Allows releasing escrow payouts as transfers using idempotency keys, with reliability gating to prevent duplicate payouts.
Allows posting approval cards with interactive Approve/Reject buttons, waiting for a human decision, retracting the card when a workflow rolls back, and sending settlement receipts as replies.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@TriadrAudit PR #42, get team sign-off on Telegram, then release escrow"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Triadr - Self-Healing Multi-App Agent & Reliability Engine
Built for the Multi-App AI Agent Hackathon (
multiappagenthackathon.com) Connected apps: GitHub (code audit) · Telegram (team approval) · Stripe (escrow payout) Stack: Model Context Protocol · Python 3.11+ · FastAPI · Next.js 14 · Tailwind CSS License: Apache 2.0
Triadr takes one sentence - "Audit PR #42, get team sign-off on Telegram, then release $2,500 from escrow to the contractor" - and carries it across three external apps as a six-step workflow. Every side effect passes through a reliability gate that validates, retries, reroutes, deduplicates and, when a step is genuinely unrecoverable, rolls the whole workflow back. Every decision lands on a SHA-256 hash chain you can verify yourself.
The guarantee: a run ends fully applied or fully reverted. Never half-executed.
Demo video
Watch the 2-minute demo - the whole workflow running against the real GitHub, Telegram and Stripe APIs, including a live approval pressed on a phone, a real payout, a fault storm the gate heals, and a rollback that undoes itself.
![]()
Related MCP server: 0nMCP
Live demo
Live app | |
Run console | |
Demo video | https://youtu.be/It-J686I8NI (2 min) |
Direct to the control plane |
The front end is on Vercel and proxies to a FastAPI control plane on a VPS; the second row is that control plane served directly, as a fallback if the proxy is unavailable.
The public deployment is deliberately credential-free: all three apps run in SIMULATED mode and the UI says so on every card. That is not a limitation of the integration - it is the only mode that works for a shared URL, because a live run posts an approval card to one specific person's Telegram and waits for them to press a button. The live runs against the real GitHub, Telegram and Stripe APIs are shown in the demo video and reproducible with your own credentials in five minutes - see §5.
Team
Member | |
MrNetwork (Ifeanyichukwu Onwo) |
Solo entry. Repository: https://github.com/mrnetwork0001/Triadr
Submission checklist
Everything the hackathon asks for, and where it is in this repository.
Required | Where |
Project overview - what it is and the problem it solves | Top of this file, and §1 What you will see |
External apps used (at least three) | GitHub (code audit) · Telegram (team approval) · Stripe (escrow payout) - §1, tool-by-tool in §11 |
Setup instructions | §3 Try it in five minutes (no accounts needed) and §5 Try it live (real credentials) |
How reliability was tested | §10 Evidence - 176 tests, a 40-run fault campaign, measured latency, a verifiable audit chain. Full write-up in docs/RELIABILITY_BRIEF.md |
Two-minute demo video | youtu.be/It-J686I8NI - 1:57 |
Judges can access the repo and demo | This repository is public; the video is on YouTube; the app is live at usetriadr.vercel.app |
Team | §Team - one person, email included |
Contents
Submission checklist - every requirement and where it lives
Demo video - 2 minutes, start here
1. What you will see
The fastest way to see it is the 2-minute demo video. Below is the same workflow in writing, and what can go wrong at each step:
# | App | Step | If it fails |
1 | GitHub | Audit the pull request - diff surface, sensitive paths, tests, CI - into a 0-100 risk score | retried, rerouted; unrecoverable → run stops cleanly |
2 | GitHub | Write the verdict onto the commit as a status check | non-critical: the run continues |
3 | Telegram | Post an approval card with real Approve / Reject buttons | unrecoverable → run stops cleanly |
4 | Telegram | Wait for a human to press a button | timeout → payout skipped, nothing moved |
5 | Stripe | Release the escrow payout as a transfer, under an idempotency key | unrecoverable → the card is retracted and the status reset |
6 | Telegram | Post the settlement receipt as a reply to the card | non-critical: the run continues |
Four scenarios exercise the happy path and every failure path - see §6.
Under a fault storm that fails ~75% of calls on first attempt, across 40 runs:
Faults absorbed | 356 |
Steps self-healed | 130 |
Runs ending fully applied | 26 |
Runs ending fully rolled back | 14 |
Runs left half-executed | 0 |
Duplicate payouts | 0 |
Audit chains that verify | 40 / 40 |
Reproduce it yourself: python3 scripts/campaign.py --runs 40
2. Prerequisites
Requirement | Notes |
Python 3.11+ | The engine ( |
Node.js 18+ and npm | Only for the web app. |
macOS or Linux | Windows works under WSL. |
Optional: GitHub, Telegram and Stripe accounts | Only for §5. Everything else runs on deterministic simulators. |
3. Try it in five minutes - no accounts needed
Every app falls back to a simulator when its credential is absent, and says so in every result, so the whole demo runs offline.
3.1 Clone
git clone https://github.com/mrnetwork0001/Triadr.git
cd Triadr3.2 Run the agent in your terminal (30 seconds)
python3 main.py --scenario allYou will see four runs and a comparison table:
scenario outcome steps faults healed undone chain ms
clean APPLIED 6/6 0 0 0 valid 602
chaos APPLIED 6/6 15 6 0 valid 1384
rollback ROLLED BACK 2/5 4 0 2 valid 612
rejected APPLIED 4/6 0 0 0 valid 460How to read it: chaos absorbed 15 injected faults and still settled the payout once;
rollback lost Stripe after the approval card was posted, so it undid the two side
effects it had already made (undone 2) and moved no money; rejected skipped the payout
by an explicit condition. Every run's audit chain verifies.
Each run also writes .triadr/<run_id>.jsonl and an attestation. Verify one:
python3 main.py --verify .triadr/<run_id>.jsonl3.3 Run the web app
Two processes: the FastAPI control plane and the Next.js front end.
# one-time setup
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
npm install
# terminal 1 - control plane (API + live event stream)
.venv/bin/uvicorn server:app --port 8000
# terminal 2 - front end
npm run dev # http://localhost:3000If port 8000 or 3000 is taken on your machine, pick others and tell the front end where the API is:
.venv/bin/uvicorn server:app --port 8770
TRIADR_API_URL=http://127.0.0.1:8770 npx next dev --port 8771Route | What it is |
| Landing page: the problem, the three apps, the eight gate stages, scenarios, evidence, audit log, how to run it. Works with the API down; adds live app status and a freshly measured benchmark when it is up. |
| The run console. Pick a scenario, run the agent, watch every gate decision stream in, inspect the sealed audit chain. |
4. Guided walkthrough of the dashboard
Open http://localhost:3000/dashboard. Left to right, top to bottom:
Left rail - the five sections of the console, the three connected apps with a green dot for live or grey for simulated, and whether the control plane is online.
Run console - the instruction (pre-filled), a scenario selector, and Run agent. Start with Clean run.
Press Run agent. Within a second:
KPI strip fills with measured numbers: reliability score, faults absorbed, steps self-healed, and the gate's own overhead in microseconds.
Execution tree shows the six steps turning from queued to running to applied. Click any step to open its gate attempts: each physical attempt, which endpoint it hit, the fault it got, and the backoff before the next try.
Gate event stream scrolls every decision as it happens:
gate.fault,gate.backoff,gate.ok,saga.compensatedand so on.Cryptographic audit log seals when the run ends: entry count, Merkle root, and a Chain verified badge that was recomputed from the entry bodies, not stamped.
Now run Chaos storm. Watch steps go amber (self-healed) and expand one - you will see
TIMEOUTon the primary gateway,RATE_LIMITEDon the replica, then success. The payout still settles exactly once.Run Stripe outage. Stripe is forced down after the approval card is posted. Watch the run stop, then the rollback: the Telegram card is retracted and the commit status reset, in reverse order. Result banner: rolled back cleanly, 2/2 side effects reversed, no partial state remains.
Run Reviewer rejects. The payout step is skipped by condition, and the receipt with it.
Everything you just watched came from the simulators. To make it real, keep going.
5. Try it live - real GitHub, Telegram and Stripe
Each app switches itself to LIVE the moment its credential is present. You can bring them up one at a time; the readiness check works per app. Full detail, including the minimum scopes, is in docs/LIVE_SETUP.md.
5.1 Credentials (about 15 minutes total)
cp .env.example .env # then fill in the values belowApp | What you need | Where |
GitHub | A fine-grained personal access token scoped to one repo you own, with Pull requests: read and Commit statuses: read & write (Checks: read is optional). Plus an open pull request in that repo. | github.com → Settings → Developer settings → Fine-grained tokens |
Telegram | A bot token from @BotFather ( | Telegram app |
Stripe | A test-mode secret key ( | dashboard.stripe.com |
GITHUB_TOKEN=github_pat_… TRIADR_REPO=owner/repo TRIADR_PR=1
TELEGRAM_BOT_TOKEN=123456:AA… TRIADR_TELEGRAM_CHAT_ID= # left blank - discovered below
STRIPE_SECRET_KEY=sk_test_… TRIADR_CONTRACTOR_ACCOUNT= # left blank - created below
TRIADR_APPROVAL_TIMEOUT=1205.2 Prove each app, in stages
python3 scripts/live_check.pyRead-only. Prints PASS / FAIL / SKIP per tool with the exact fix for each failure.
On the first run it also discovers your Telegram chat id and prints the line to add
to .env.
python3 scripts/live_check.py --stripe-setupFunds the test balance (a $100 test-mode charge) and creates a test payee through
Stripe's Accounts v2 API, printing an acct_… id to add to .env and an onboarding
link. Open the link and complete the form with test data - use the Test (Non-OAuth)
bank and Stripe's test values (000 000 0000, DOB 01/01/1901, SSN 0000). Until this
is done the payee's transfers capability is restricted and every transfer is refused.
python3 scripts/live_check.py --write --payoutA real commit status on your PR, a real Telegram message that deletes itself, and a real $1.00 transfer, replayed under the same idempotency key (same transfer id comes back - no double payment), then reversed.
TRIADR_APPROVAL_TIMEOUT=300 python3 scripts/live_check.py --run cleanThe whole saga, live. A card lands in your Telegram - press ✓ Approve - and the $25 transfer settles, with the receipt posted under the card. Expected output:
succeeded audit github.audit_pull_request 2641ms
succeeded status github.set_commit_status 1763ms
succeeded approval_card telegram.post_approval_card 933ms
succeeded approval telegram.await_approval 48921ms ← the human
succeeded payout stripe.release_escrow 1356ms
succeeded receipt telegram.post_message 10717ms
6/6 steps applied across 3 apps. 0 fault(s) absorbed, 0 step(s) self-healed,
0 steps left half-executed. Payout tr_… settled for USD 25.00.
chain valid: True--run rollback does the same with Stripe forced down: the card you just saw is
retracted and the commit status reset, for real.
5.3 The live demo from the dashboard
Restart the control plane after editing .env (it reads the file at startup), reload
/dashboard, and the app dots turn green. The run box now names your real repo, chat and
payee. Press Run agent, then press Approve on your phone when the card arrives -
the command bar tells you when the agent is waiting on you. Everything on screen is a
real API call; injected faults (Chaos storm) are labelled [injected] in the event stream.
Each live clean run moves $25 of test money to the test payee. --stripe-setup tops the
balance up again whenever it drops below $50.
6. Command reference
# The agent
python3 main.py # clean run
python3 main.py --scenario chaos # clean | chaos | rollback | rejected | all
python3 main.py --instruction "Audit PR #7 in acme/api, sign-off on Telegram, pay acct_1X $50 USD"
python3 main.py --json # full result as JSON
python3 main.py --bench # measured gate overhead, both phases
python3 main.py --verify <log.jsonl> # re-verify a written audit chain
# Evidence
python3 scripts/campaign.py --runs 40 # regenerates every figure in this README
python3 -m pytest tests/ -q # 176 tests
# Live readiness
python3 scripts/live_check.py # read-only checks per app
python3 scripts/live_check.py --write # + a write and its undo per app
python3 scripts/live_check.py --approve # + a real approval card; press a button
python3 scripts/live_check.py --stripe-setup # fund test balance, create/inspect the payee
python3 scripts/live_check.py --payout # + $1 transfer, replay, reversal
python3 scripts/live_check.py --run clean # full saga, live
python3 scripts/live_check.py --run rollback # full saga with Stripe forced down
# Web app
.venv/bin/uvicorn server:app --port 8000 # control plane (npm run api)
npm run dev # front end (npm run build / npm start for production)
npm run typecheck7. Configuration reference
All variables live in .env (see .env.example), loaded by every entry point. Existing
environment variables always win over the file.
Variable | Purpose | Default |
| Fine-grained PAT; presence switches GitHub to LIVE | - |
| Repository ( |
|
| BotFather token; presence switches Telegram to LIVE | - |
| User or group id (negative for groups) or |
|
| Seconds a human has to press Approve / Reject |
|
| Test-mode key; presence switches Stripe to LIVE | - |
| Connected account the escrow is released to | placeholder |
| Payout amount (major units) and ISO currency |
|
| Must be | - |
| Risk score at or above which a human must approve |
|
| HMAC key that signs each run's attestation | unsigned |
| Where audit logs are written |
|
| Comma-separated real gateways to fail over across in LIVE mode | one real API |
|
| - |
| Let Claude extract instruction parameters (never invent steps) | off |
| Where the front end proxies |
|
8. Troubleshooting
Symptom | Cause and fix |
| Another process owns the port. Use other ports: |
Dashboard says api offline | The control plane is not running, or the front end proxies to the wrong port. Start uvicorn; check |
Apps still show simulated after adding credentials | The control plane reads |
| Your real key is in |
Telegram: | Open your bot in Telegram, press Start, send any message, re-run |
Telegram: | A webhook is registered for the bot. Triadr clears it automatically and continues. |
Stripe: Stripe no longer recommends Accounts v1 | Your platform requires Accounts v2 - |
Stripe: | The payee has not finished onboarding. Re-run |
Stripe: You can only create new accounts if you've signed up for Connect | Dashboard → Connect → Get started, then re-run |
GitHub: 404 on the repository | Fine-grained tokens are per-repo: the token must be granted access to |
GitHub: no Checks permission offered | Optional. |
The approval card arrived but the run timed out | Press the button on the newest card; older cards are disarmed and answer with an "expired" toast. Raise |
| Both use |
9. How it works
"Audit PR #42, get sign-off on Telegram, then pay $2,500 from escrow"
│
▼
┌───────────────────────┐
│ Planner │ deterministic plan shape,
│ agents/planner.py │ parameters bound from text
└───────────┬───────────┘
▼
┌───────────────────────┐
│ Saga orchestrator │ 6 steps, typed dependencies,
│ agents/orchestrator │ every mutation has a rollback
└───────────┬───────────┘
▼
╔═════════════════════════════════════════════════════════════╗
║ RELIABILITY GATE - risk_gate.py ║
║ idempotency · schema · drift · rate shaping · breakers ║
║ backoff+jitter · endpoint failover · compensation ║
╚══════════┬═══════════════════┬══════════════════┬═══════════╝
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ GitHub │ │ Telegram │ │ Stripe │ MCP servers,
│ 6 tools │ │ 4 tools │ │ 4 tools │ 14 tools total
└────────────┘ └────────────┘ └────────────┘
│ │ │
└───────────────────┼──────────────────┘
▼
┌───────────────────────┐
│ SHA-256 hash chain │ tamper-evident evaluation log
│ reliability_logger │ + merkle root + HMAC signature
└───────────────────────┘The gate, in execution order
Every call to any of the three apps goes through ReliabilityGate.guard():
Idempotency ledger - a replayed key returns the recorded result. A retried payout whose response was lost in flight cannot pay twice.
Input schema validation - zero-LLM, ~1.4 µs. A malformed payload is blocked before the executor runs, so a bad call has no side effect at all.
Token bucket - client-side rate shaping sized below each vendor's documented ceiling, so Triadr sheds load before the vendor does.
Circuit breakers - per endpoint,
CLOSED → OPEN → HALF_OPEN. An open endpoint is never selected and costs no retry budget. If the whole fleet is open, one probe is still admitted rather than failing a workflow a single call would have saved.Execution with typed faults - every failure is classified (
RATE_LIMITED,TIMEOUT,AUTH_EXPIRED,PERMISSION_DENIED, …). Retryable faults back off exponentially with full jitter and honourRetry-After; terminal faults like a 403 are never retried.Endpoint failover - attempts cycle across health-ranked gateways, not the same dead host.
Response contract checking - a declared
outputSchemacatches drift on the very first call; a learned per-tool fingerprint catches it thereafter. A vendor renamingdecisiontodecision_v2is caught and rerouted instead of silently corrupting the payout decision.Compensation - if a critical step is unrecoverable, completed side effects are undone in reverse order, with a larger retry budget than the forward path.
The audit log
digest(n) = SHA256( digest(n-1) ‖ canonical_json(entry(n)) )Editing, reordering or deleting any entry breaks verification at exactly the corrupted
index. The attestation carries a Merkle root over all entries and, with TRIADR_LOG_KEY
set, an HMAC signature. run.end is recorded before the seal, so the commitment covers
the complete log.
10. Evidence
This is the section that answers "how did you test that it works".
Three independent kinds of evidence, all reproducible from this repository:
A test suite - 176 tests, run with
python3 -m pytest tests/ -q.A fault campaign - 40 full workflow runs under a storm that fails ~75% of calls on first attempt, run with
python3 scripts/campaign.py --runs 40. Result: 356 faults absorbed, 0 runs left half-executed, 0 duplicate payouts, 40/40 audit chains verify.A verifiable audit chain - every run writes a hash-chained log you can recompute with
python3 main.py --verify .triadr/<run_id>.jsonl, so the numbers above are checkable rather than asserted.
Plus a live readiness check against the real APIs (python3 scripts/live_check.py), which is
how the video's live run was proven end to end.
Measured on a laptop (python3 main.py --bench), never hardcoded:
Phase | p50 | p99 |
Input schema validation | 1.42 µs | 1.71 µs |
Full pre-flight (+ drift fingerprint) | 4.92 µs | 6.54 µs |
The landing page re-measures this on every load when the control plane is up, and the dashboard shows the percentiles from your own run.
python3 -m pytest tests/ -q # 176 testsCovering schema validation edge cases, breaker transitions, backoff bounds, endpoint
routing, idempotency, drift detection, chaos determinism, the MCP JSON-RPC surface, the
LIVE request wiring for all 14 tools (method, URL, encoding, auth and idempotency
headers, verified against a recorder), hash-chain tamper evidence, and an 8-seed property
test asserting the core invariant: every run ends fully applied or fully reverted.
The suite is hermetic: a developer's .env can never turn a unit test live.
The full write-up for judges is docs/RELIABILITY_BRIEF.md.
11. Triadr as an MCP server
The 14 tools are exposed over the standard MCP stdio transport, dependency-free - and every call an MCP host makes is gate-supervised, so the host inherits retry, rerouting, idempotency and rollback for free.
claude mcp add triadr -- python3 /path/to/Triadr/mcp_servers/stdio_server.pyApp | Tools |
GitHub |
|
Telegram |
|
Stripe |
|
Every tool that mutates remote state declares the tool that undoes it - enforced by a test.
12. Safety
Stripe refuses to move money on an
sk_live_key unlessTRIADR_ALLOW_LIVE_MONEY=1is explicitly set.The planner's shape is fixed in code. An LLM may only extract parameters, never invent a step - a hallucinated extra
release_escrowwould be a financial incident.Condition evaluation is a deliberately tiny parser, not
eval.Every payout carries an idempotency key derived from the workload, not the attempt.
Every app reports
LIVEorSIMULATEDin results, dashboard and audit log; injected faults are labelled[injected].Secrets never reach a log: the Telegram bot token is redacted from every fault, and
.env/.triadr/are git-ignored.
13. Repository layout
Path | |
| The reliability gate. Stdlib only, no LLM on the hot path. |
| Instruction → typed plan with a fixed shape. |
| Saga engine with reverse-order compensation. |
| Hash-chained evaluation log, Merkle root, signature. |
| GitHub, Telegram and Stripe servers, the registry, and the MCP stdio server. |
| Stdlib |
| CLI: scenarios, benchmark, verifier. |
| FastAPI control plane with SSE streaming. |
| Reproduces every figure in this README. |
| Proves each app against its real API; Stripe test setup. |
| 176 tests, hermetic. |
| Landing page, its sections, motion kit and single-sourced figures. |
| Run console: sidebar, top bar, command bar, KPI strip and the live panels. |
| Header lockup, vendor logos, favicon. |
| System & reliability brief for judges. |
| Credentials, minimum scopes, Stripe Connect setup, what is real vs injected. |
| Positioning, voice and vocabulary. |
License
Apache 2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
The AI orchestration agent for modern software teams.
Hosted runtime for persistent agent teams, durable workflows, memory, schedules, and goals.
Agent-native security, trust, reliability, data and procurement tools for AI workflows.
Reliable async execution for agent tool calls: schema gating, retries, idempotency, audit trail.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to execute formal, stateful workflows with typed contracts, postcondition enforcement, and structured retry logic.1Apache 2.0
- AlicenseNot gradedqualityDmaintenanceA universal AI API orchestrator that connects to 17+ services (Stripe, Slack, GitHub, etc.) and enables natural language task execution, multi-step automation, and complex orchestration across them without coding.131 npm1MIT
- FlicenseBqualityCmaintenanceEnables AI coding assistants to run a machine-verified DESIGN→PLAN→EXECUTE→VERIFY→COMPLETE workflow with human approval gates, state integrity checks, and DAG task scheduling.7-

polyflowofficial
AlicenseNot gradedqualityBmaintenanceEnables AI agents to run model-checked workflows durably, receiving one work order at a time with guarantees on admission.84 npmApache 2.0