How to Look Up Runbooks from a Knowledge Collection When an Alert Fires
When an alert webhook arrives, query a persistent Knowledge collection of your operational runbooks in Query mode with a Response Schema, then post the matched remediation steps and owning team straight into the incident's Slack thread for the on-call engineer.
What This Integration Does
On-call engineers lose minutes hunting for the right runbook every time a monitoring tool fires an alert. This Spojit workflow closes that gap. The moment your monitoring or alerting system POSTs an alert to a Spojit Webhook trigger, the workflow searches a workspace Knowledge collection that holds your runbooks (one document per service or failure mode), pulls back the matching remediation steps and the owning team, and drops that answer directly into the Slack thread for the incident. The engineer sees "here is what to do and who owns it" without leaving the channel.
The run model is event-driven and stateless per alert. The Webhook trigger receives one alert as a JSON body and returns 202 with an executionId immediately, so your alerting tool is never held open. A Knowledge node in Query mode reads from a persistent, workspace-scoped collection you populate ahead of time, so it leaves no state behind and re-runs are safe: the same alert simply produces the same lookup again. A Condition node decides whether the lookup found a confident match before anything is posted, and the Slack connector writes the result into the channel (optionally threaded under an existing incident message). Each alert is an independent execution in your history.
Prerequisites
- A Slack connection added under Connections -> Add connection, with permission to post messages to the channel you use for incidents.
- A persistent Knowledge collection (for example named
Runbooks) created in the Knowledge section of the sidebar, with one document per service or failure mode uploaded and showing status READY. Note the embedding model chosen at creation; it is fixed for the life of the collection. - A Webhook signing connection. For an alerting tool that signs its requests with a shared secret, add a connection using the Custom HMAC scheme so Spojit can verify each alert. See the prerequisite link in Setting Up a Webhook Connection.
- The Slack channel ID (or name) for your incident channel, and, if you thread replies, a way for the alert payload to carry the parent message timestamp.
Step 1: Receive the alert with a Webhook trigger
Add a Trigger node and set its type to Webhook. Choose your Custom HMAC signing connection so each incoming alert is verified before the workflow runs. Save the workflow to reveal the unique webhook URL, then paste that URL into your monitoring or alerting tool as the alert destination. The trigger parses the POSTed JSON and exposes it as {{ input }}. A typical alert body looks like this:
{
"alertName": "API latency high",
"service": "checkout-api",
"severity": "critical",
"summary": "p95 latency above 2s for 5 minutes",
"channel": "C0123INCIDENT",
"threadTs": "1718900000.123456"
}
Spojit responds with 202 and an executionId right away, so the alerting tool is not blocked while the lookup runs.
Step 2: Query the runbook collection with a Knowledge node
Add a Knowledge node and set Mode to Query. In Collection pick your persistent Runbooks collection. In Prompt, compose a natural-language question from the alert so the search targets the right runbook:
Find the runbook for the service "{{ input.service }}" matching this alert:
"{{ input.alertName }} - {{ input.summary }}" (severity {{ input.severity }}).
Return the remediation steps and the team that owns this service.
Leave Result Count at its default of 5 so several candidate chunks inform the answer, and pick a Model for synthesis. Set an Output Variable, for example runbook. This node runs against the same embedding model the collection was created with, so embed and query stay aligned automatically.
Step 3: Force structured output with a Response Schema
Still on the Knowledge node, fill in the Response Schema field so the answer comes back as predictable JSON instead of prose. This lets the later steps read individual fields reliably rather than parsing free text. Use a schema like:
{
"type": "object",
"properties": {
"found": { "type": "boolean" },
"service": { "type": "string" },
"owningTeam": { "type": "string" },
"remediationSteps": {
"type": "array",
"items": { "type": "string" }
},
"confidence": { "type": "number" }
},
"required": ["found", "remediationSteps", "owningTeam", "confidence"]
}
The result is available as {{ runbook.found }}, {{ runbook.owningTeam }}, {{ runbook.remediationSteps }}, and {{ runbook.confidence }}. The confidence field gives you a cheap, machine-readable signal for the branching in the next step.
Step 4: Branch on whether a confident match was found
Add a Condition node after the Knowledge node. Configure the true branch to check that the lookup actually matched a runbook, for example {{ runbook.found }} is true AND {{ runbook.confidence }} is greater than 0.6. Route the true branch into Step 5 so a confident match is posted as remediation guidance. Route the false branch into Step 6 so a low-confidence or no-match alert still reaches the on-call engineer with an honest "no runbook found" message instead of a confidently wrong one.
Step 5: Post the matched runbook into the Slack thread
On the true branch, add a Connector node on the Slack connector in Direct mode and select the send-message tool. Map the fields:
channel:{{ input.channel }}(the incident channel from the alert, or a fixed channel ID).thread_ts:{{ input.threadTs }}so the runbook lands as a reply under the existing incident message. Omit this field to post a new top-level message instead.text: a templated summary the engineer can act on immediately, for example:
:rotating_light: *{{ input.alertName }}* on `{{ input.service }}` ({{ input.severity }})
*Owning team:* {{ runbook.owningTeam }}
*Remediation:*
{{ runbook.remediationSteps }}
Direct mode is deterministic and costs no AI credits, which is what you want for a predictable single post per alert. If you would rather have the intelligent layer format the message conversationally, you could instead use Agent mode, but Direct mode keeps this step cheap and reproducible.
Step 6: Send a fallback message when no runbook matches
On the false branch, add a second Connector node on the Slack connector in Direct mode using send-message again, posting to the same {{ input.channel }} and thread_ts. Make the text clear that no confident runbook was found so the engineer knows to investigate manually and, ideally, write a new runbook afterward:
:warning: No matching runbook found for *{{ input.alertName }}* on `{{ input.service }}`.
On-call: please investigate manually and add a runbook to the Runbooks collection.
You can extend this branch later by paging a specific team or escalating, but a plain Slack notice keeps the workflow honest about what it did and did not find.
Tips
- Keep one runbook document per service or failure mode and put the owning team near the top of each document. Cleaner source documents produce sharper Knowledge answers.
- Use Slack
lookup-user-by-emailin a follow-up step if your runbook returns an owner email and you want to @-mention that person directly in the thread. - Build and scaffold this workflow quickly with Miraxa, the intelligent layer across your automation, with a prompt like "Add a Knowledge node in Query mode against the Runbooks collection with a Response Schema, then a Condition node on `{{ runbook.found }}`, then a Slack send-message node." Then fine-tune the fields in the properties panel.
- If your alerting tool can send a deduplication header, enable the trigger's opt-in dedup so repeated fires of the same alert do not spam the thread.
Common Pitfalls
- Embed and query must use the same embedding model. Because the model is fixed when a collection is created, do not recreate the collection with a different model and expect old queries to behave; rebuild documents if you switch.
- Documents that still show status PROCESSING are not yet searchable. Wait for READY before relying on a runbook in a live alert path.
- Without a Response Schema the Knowledge node returns prose, and
{{ runbook.found }}or{{ runbook.owningTeam }}will be empty. Always set the schema if downstream steps read individual fields. - If the alert body does not include a parent message timestamp, leaving
thread_tsmapped to an empty value posts a new message rather than threading. Decide per channel whether you want threaded replies and only mapthread_tswhen the value is present. - The Webhook trigger rejects unsigned or wrongly signed requests when a signing connection is set. Confirm your alerting tool signs with the exact secret configured on the Custom HMAC connection, or alerts will silently fail verification.
Testing
Before pointing your real monitoring tool at the workflow, send one crafted alert to the webhook URL for a service you know has a runbook in the collection, using a test Slack channel ID in the payload. Confirm in the execution history that the Knowledge node returned {{ runbook.found }} as true with a sensible confidence, that the Condition node took the true branch, and that the message appeared in the test channel (threaded if you supplied threadTs). Then send a deliberately unknown service name to confirm the false branch posts the fallback notice. Once both paths behave, swap in the live incident channel and connect your alerting tool.