Webhook incident responder
Goal
When your monitoring system fires an alert, you want more than a raw page, you want a
first-pass triage waiting in your channel: what broke, how bad, the likely cause, and
a first step. A webhook trigger turns the alert into a fresh agent session; the
agent assesses it and posts a summary via inform_user.
This recipe shows the webhook trigger and passing its payload into the session.
Every step is shown two ways: first in the console (which page to open, what to
click, which fields to fill), then a Via the CLI block with the exact primectl
command. Pick whichever you prefer; the two paths build the same objects.
Ingredients
- An LLM provider and a channel with a workspace bound to it (see the stock-news monitor for channel and reply-binding setup).
- Optionally the web toolset or workspace file tools so the agent can investigate (search the error, read a log) before summarizing.
If you have not connected primectl yet, see "Connecting the CLI" in the
RAG knowledge base recipe.
Walkthrough
1. Create the responder agent
In the console:
- Go to Compute > Agents and click New agent.
- On Basic set ID to
incident-responder, add a Description, and pick the LLM provider and Model. - On Tools check
misc__inform_user. - On Advanced paste the system prompt (below) and set max tool turns to
5. Click Create.
Via the CLI:
primectl create -f incident-responder.yaml
kind: agent
spec:
id: incident-responder
description: Triages incidents from alerts and notifies the channel.
model: { provider_id: <llm>, model_name: <model> }
tools:
- misc__inform_user
max_tool_turns: 5
system_prompt:
- >-
You are an incident responder. An alert payload is in your input. Assess
likely severity, name 1-2 plausible causes and a first step, then call
inform_user ONCE with a concise triage summary (service, severity, likely
cause, first step). Then stop.
2. Create a webhook trigger
In the console:
- Go to Automation > Triggers and click New trigger. Set the Kind to
Webhook, give it a slug (
incident), Enable it, and click Create. - Open the trigger; its detail page shows the webhook URL. That public URL is
POST /v1/webhooks/{token}, what your monitoring system calls. Treat the token as a secret.
Via the CLI:
primectl create -f trigger.yaml
kind: trigger
spec:
slug: incident
name: Incident webhook
config: { kind: webhook }
enabled: true
The created trigger carries the webhook token in config.token; read it back
with primectl get trigger <trigger-id> -o json -r. The public URL is
POST /v1/webhooks/{token}.
3. Wire a subscription that carries the alert
The webhook body is exposed to the payload template as {{ webhook_body }} (raw
string; webhook_headers, webhook_query, webhook_method are available too).
Render it into the agent's instructions, and point the subscription at the
channel-bound workspace.
In the console:
- Open the trigger and click New subscription. Set the Action to
agent_fresh_session, pick the
incident-responderagent and the channel-bound workspace, set the Payload template to render the alert (below), and click Create.
Via the CLI, the subscription is nested under the trigger, so create it with the
call trigger subscriptions custom operation (pass the trigger id create echoed
back):
primectl call trigger subscriptions <trigger-id> -f subscription.yaml
config: { kind: agent_fresh_session, agent_id: incident-responder, workspace_id: <channel-bound-workspace> }
payload_template: "Incident alert received: {{ webhook_body }}. Triage it and post a summary."
A few things worth knowing:
- The webhook URL is unauthenticated except for the token, treat the token as a
secret. For stronger guarantees set
config.hmac_secret; callers must then sendX-Primer-Signature: HMAC-SHA256(secret, body)or get a 401. webhook_bodyis the raw string, not parsed JSON, pass it whole (the agent reads it fine), or parse fields in the template if your renderer has a JSON filter.- Deliver from the agent session. As in the stock-monitor recipe,
inform_userreaches the channel from anagent_fresh_session(returnsdelivered_to: 1); keep the notify in the agent, not a graph node. - Webhooks are rate-limited and body-capped (1 MB) server-side.
Testing
Simulate an alert by POSTing to the webhook. The webhook is a public,
token-authenticated endpoint with no first-class console button or primectl verb
(your monitoring system calls it directly), so the simplest hands-on test is curl,
or the primectl raw escape hatch:
primectl raw POST /v1/webhooks/<token> -f alert.json
where alert.json is:
{"service": "payments-api", "error": "5xx error rate 40%, p99 latency 8s", "region": "us-east"}
Expected outcome (verified):
- The webhook returns
202with{"status": "accepted"}and adelivery_id, and fires the subscription, creating a fresh session from the alert. The fired session is created, claimed, and runs to terminalended/completed(the dispatch hands the fired session to the runner, so it actually executes). Find it on the Sessions page filtered to the bound workspace (it is tagged with the trigger id); on the CLI the session list takes aworkspace_idfilter through theprimectl rawescape hatch (primectl raw GET /v1/sessions --param workspace_id=<workspace-id> -o json). - The agent triages the alert (the rendered
{{ webhook_body }}is in its instructions) and callsinform_user, so a summary lands in your channel (the tool result showsdelivered_to: 1). The alert-to-channel delivery is verified live, the same path proven in the stock-monitor recipe.
Read the session transcript back with
primectl workspace files get <workspace-id> .state/sessions/<sid>/messages.jsonl --content
to confirm the rendered alert and the inform_user triage call.
Point a real alerting rule (Grafana, Datadog, an uptime checker) at the webhook URL
and you have hands-off first-response triage. Give the agent the web toolset and it
can look up the error before summarizing.