Your API just healed itself. Autoregent makes sure you find out.
An API gateway that heals failing upstreams but is structurally incapable of doing it silently. When a request drifts from its expected schema, Gemini diagnoses it live in the request path and proposes a fix — but the caller’s 200 OK and the disclosure event fire together, every time. A heal is never a secret, and a write-path route is never healed at all.
Live gateway: https://autoregent-production.up.railway.app Live dashboard: https://vladlen-codes.github.io/autoregent/ Docs: DOCUMENTATION.md
Read paths may be healed. Write paths may never be healed.
Informational routes (balance lookups, transaction history) are eligible for AI-diagnosed schema remediation. Transactional routes (ledger writes, transfers, charges) get exactly one behavior on failure: fail loudly, preserve the idempotency key, trip the circuit. No AI-generated payload ever touches a write path — the route classifier enforces this before the request reaches any heal logic, not as a policy the model could be prompted around.
INFORMATIONAL or TRANSACTIONAL before dispatch.drift_type == unrecoverable → fail loud. Gemini times out (3s) or errors → fail loud. Gemini can authorize a heal; nothing it says can force one through.200 and a set of X-Autoregent-* headers (including an HMAC-signed trace). Simultaneously, a signed, queryable event lands in /events with the original payload, the healed payload, and Gemini’s full reasoning side by side.python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in GEMINI_API_KEY
uvicorn app.main:app --reload --port 8000
| Method | Path | Purpose |
|---|---|---|
| GET | /health |
Liveness + per-route circuit states + budget config |
| GET | /events |
Append-only, HMAC-signed heal-event log (JSON) |
| ANY | /proxy/{path} |
The gateway itself — classifies, dispatches, heals or fails loud |
| ANY | /mock/{scenario} |
Flaky mock upstream, informational routes |
| ANY | /mock/txn/{scenario} |
Same scenarios, mounted where the classifier tags the route TRANSACTIONAL |
Mock scenarios: healthy, field_rename, type_change, timeout, 500, cascading.
BASE=https://autoregent-production.up.railway.app # or http://localhost:8000
# Clean pass
curl $BASE/proxy/mock/healthy
# Schema drift -> Gemini diagnoses it live, heals it, discloses it. Real API call, not mocked.
curl -i $BASE/proxy/mock/field_rename
# Same drift, but the classifier tags this route TRANSACTIONAL -> always fails loud,
# idempotency key preserved, circuit trips on the first failure. No heal pipeline, ever.
curl -i -H "Idempotency-Key: abc-123" $BASE/proxy/mock/txn/field_rename
# Cascading failure -> loop detector suppresses the retry instead of cycling forever
curl $BASE/proxy/mock/cascading
# Hammer a route past its rolling-window budget -> circuit trips OPEN,
# subsequent requests fail fast until the cooldown elapses
for i in $(seq 1 6); do curl -s -o /dev/null -w "%{http_code}\n" $BASE/proxy/mock/type_change; done
curl $BASE/events # every heal/fail/suppress/trip, signed, with the full call stack
curl $BASE/health # circuit state per route
Logs are structured JSON on stdout.
A Next.js static-export dashboard (dashboard/) polls /health and /events client-side and renders live circuit state, budget burn, and the event feed — including a divergence-alert banner that fires the instant a new heal lands, and a per-event pipeline diagram showing exactly which stage a request passed or stopped at.
cd dashboard
npm install
npm run dev # http://localhost:3000
Deploys automatically to GitHub Pages via .github/workflows/deploy-dashboard.yml on every push touching dashboard/. The gateway URL is switchable at runtime in the dashboard’s header (saved to localStorage), with one-click presets for local and live.
Live on Railway. Connect the repo, set GEMINI_API_KEY and HMAC_SECRET as service variables, generate a public domain, then set:
UPSTREAM_BASE_URL=http://localhost:8080
Not the public domain — localhost. The mock upstream lives in the same process as the proxy, and several PaaS providers (Railway included) block a container from calling back into its own public domain from inside itself (a “hairpin” request rejected at the edge). Since it’s the same process, there’s no reason to leave the container at all.
Cloud Run was the original target; GCP billing verification failed on the account used for this build (confirmed by the API itself, not just a console glitch), so this documents the intended path rather than what’s actually running:
gcloud auth login
gcloud config set project <your-project-id>
gcloud services enable run.googleapis.com cloudbuild.googleapis.com
gcloud run deploy autoregent-gateway \
--source . \
--region asia-south1 \
--allow-unauthenticated \
--set-env-vars GEMINI_API_KEY=<your-key>,UPSTREAM_BASE_URL=http://localhost:8080
Stated openly rather than discovered by a judge: state is in-memory, so this is single-node and a restart clears event history. The HMAC trace signature proves integrity, not non-repudiation — a real deployment needs asymmetric signing into WORM storage. There’s no replay protection on the trace header. Circuit state isn’t shared across instances, so horizontal scaling would currently break budget enforcement.
BSD 3-Clause — see LICENSE.