- contact@insightairesolve.com
InsightResolve runs inside your environment — your cloud, your alert sources, your model. Start on a laptop with the demo stack, point real webhooks at it, then take the same containers to production. This is how it fits together.
InsightResolve is three containers and a database: the API, the console, and the InsightWorker engine that executes runbook steps. Alerts arrive as webhooks; everything the agent learns is written to Postgres and shown live in the console.
Prometheus, Alertmanager, Grafana, a PagerDuty stand-in, two instrumented services and InsightResolve — one docker compose up.
PagerDuty v3, Alertmanager, Grafana and a generic JSON shape — all normalized into one incident model.
Webhooks →Steps, variables, conditions and match rules — what each one is, how they resolve at run time, and how versions work.
Runbook model →Everything the console does is a REST call with a bearer token or an API key. Automate runbook changes, replay incidents, pull RCAs.
API →Three tiers, the same shape as every Insight product: a React console, a FastAPI service, and the InsightWorker agent engine. State lives in Postgres; the console gets live updates over SSE.
The API and the worker are stateless. Scale them by adding replicas. Incidents, executions, step outputs, RCAs and every runbook version live in Postgres, which you run as a managed service with backups.
| Component | What it is | Scales by | State |
|---|---|---|---|
| Console | Static React app (nginx) — dashboard, incidents, runbook editor, users & access, integrations | Replicas behind the LB / CDN | Stateless |
| API | FastAPI — webhooks, incidents, runbooks, executions, identity, connection registry | Horizontal replicas | Stateless |
| InsightWorker | The agent engine that executes runbook steps with the operations skills | Autoscale on queued executions | Stateless |
| Postgres | Incidents, executions, runbooks & versions, RCAs, metrics, identity, connections | Vertical + replicas | Durable |
| Model provider | Your chosen endpoint for the ai.* steps | Provider concurrency | External |
| Identity provider | Okta, Entra ID, Google or any OIDC issuer; local accounts for a lab | Managed | External |
The demo brings up everything the loop needs on one machine. PagerDuty is SaaS, so a stand-in with the same three surfaces (Events API in, incident REST out, webhook v3 events) takes its place.
git clone https://github.com/verticalserve/insightresolve-api
cd insightresolve-api/demo
cp .env.example .env
docker compose up -d --build # ~3 minutes the first time
./demo.sh errors # api-gateway fails 30% of requests
./demo.sh payment-latency # payment-service slows down
./demo.sh recover # sources send resolved; incidents close with MTTR
| What | Where |
|---|---|
| InsightResolve console | http://localhost:5218 — admin@demo.local / the password in .env |
| API & OpenAPI | http://localhost:8118/docs |
| Grafana | http://localhost:3000/d/resolve-demo |
| PagerDuty (mock) · Alertmanager · Prometheus | :8085 · :9093 · :9090 |
Within a minute of ./demo.sh errors, Prometheus fires HighErrorRate, Alertmanager routes it to PagerDuty, PagerDuty webhooks InsightResolve, and the incident appears matched to API Gateway High Error Rate Triage with its execution queued.
NormalizedAlert: source, external id, alert name, title, severity, service, labels, URL, start time, resolved flag.ai_triage execution.Four public endpoints. When RESOLVE_WEBHOOK_TOKEN is set, callers present it as ?token= or X-Resolve-Webhook-Token. A connection query parameter names the registered connection the sender belongs to.
| Endpoint | Accepts | Notes |
|---|---|---|
POST /api/webhooks/pagerduty | Webhook v3 events (incident.triggered, .acknowledged, .resolved) | Custom details become labels, so the Prometheus labels ride through PagerDuty |
POST /api/webhooks/alertmanager | Alertmanager webhook groups | One incident per alert; status: resolved closes it |
POST /api/webhooks/grafana | Grafana unified alerting webhook | Panel and dashboard URLs kept on the incident |
POST /api/webhooks/generic | {alert_name, title, severity, service, labels, external_id, url, status} | A list, or {alerts: [...]}, is several alerts |
A runbook is normalized into rows, not stored as one JSON document. That is what lets the console reorder a step with one update, two people edit different steps at once, and a version diff say “changed threshold in step 3”.
| Table | Holds |
|---|---|
| runbook | name, slug, category, team, status (draft · active · archived), severity filter, tags, effectiveness, times executed, current version |
| runbook_step | ordered steps: action type, parameters (JSONB), save_as, timeout, retries, continue-on-fail |
| runbook_step_condition | run_if · skip_if · branch with an expression and, for branch, a target step |
| runbook_variable | {{name}} → expression or literal, with a default |
| runbook_match_rule | alert-name and service globs, severity set, label containment, source, expression, priority |
| runbook_version | an immutable snapshot of all of the above, with a change note and an auto-generated diff summary |
Variables resolve in order: incident context ({{incident.labels.service}}), then runbook variables, then the outputs of earlier steps ({{error_rate}}, {{classification.category}}).
| Family | Actions |
|---|---|
| PagerDuty | pagerduty.get_incident · acknowledge · resolve · add_note |
| Prometheus & Alertmanager | prometheus.instant · range · alerts · alertmanager.alerts · silence |
| Grafana | grafana.dashboard · annotate |
| Kubernetes | k8s.pods · logs · events |
| Data pipelines | airflow.dag_status · task_logs · trigger · dbt.test_results · source_freshness |
| Data & tickets | postgres.query · jira.create · jira.search · slack.post · http.request · bash.exec |
| AI | ai.classify · ai.summarize · ai.decide |
| Logic | gate · assign · wait · notify · loop · parallel · human.approve |
A rule scores one point for each field it sets that matches the alert; a field it sets that does not match disqualifies it. The best score wins; ties go to rule priority, then to the runbook’s effectiveness. Test any rule from the console against a past incident or a mock payload.
{{variable}} == 'value' {{variable}} != 'value'
{{variable}} > 5.0 {{variable}} contains 'OOMKilled'
{{variable}} in ['critical', 'high']
{{variable}} matches 'error.*timeout'
| Variable | Meaning |
|---|---|
INSIGHT_DATABASE_URL / _SECRET / _SCHEMA | Postgres without a password in the URL; the password is a secret reference (AWS SM, Key Vault, GCP SM, OCI Vault, a mounted file). Schema resolve. |
INSIGHT_JWT_KEY_REF | The token-signing key pair, as a secret reference. One pair across Insight products gives single sign-on. |
INSIGHT_LLM_PROVIDER · INSIGHT_CHAT_MODEL | bedrock · azure_openai · vertex · oci · openai (any OpenAI-compatible endpoint) |
RESOLVE_WEBHOOK_TOKEN | Shared token webhook senders must present |
DEDUPE_WINDOW_MINUTES | How long a repeat folds into the open incident (60) |
WORKER_URL / WORKER_CLI | Where InsightWorker is |
Sign-in is local or any OIDC provider (Okta, Entra ID, Google). Group-to-role rules map directory groups onto roles at every sign-in. admin holds every role; curator edits runbooks; every signed-in person reads and acts on incidents. API keys are created under Users & access, shown once, and carry scopes as roles. Every change is in the audit trail.
Every response is the envelope {"status": "SUCCESS" | "FAIL", "data": ..., "error_message": ...}. Authenticate with a bearer token from POST /api/auth/login or an API key. The full OpenAPI document is at /docs on your instance.
POST /api/auth/login {"username": "...", "password": "..."}
GET /api/dashboard
GET /api/incidents?status=open&severity=critical
GET /api/incidents/{id} executions, steps, RCA
POST /api/incidents/{id}/retry match again, open a fresh execution
POST /api/incidents/{id}/escalate
GET /api/runbooks POST /api/runbooks PUT/DELETE /api/runbooks/{id}
POST /api/runbooks/{id}/activate /clone POST /api/runbooks/from-template/{tid}
GET/POST /api/runbooks/{id}/steps|rules|variables|versions
POST /api/runbooks/{id}/steps/reorder POST /api/runbooks/{id}/rules/test
POST /api/runbooks/match which active runbook takes this alert
GET /api/user/getAll /roles /providers /api-keys
GET /api/connections /connectors
Want a walkthrough on your stack? Talk to us — we’ll connect a demo instance to your alert sources and port two of your runbooks live.