AI Root Cause Analysis for Zabbix Problems

Zabbix runs a large part of the world's server monitoring, often in teams with hundreds of hosts and thousands of triggers. When a trigger fires, the on-call engineer opens the problem, looks at the item graph, checks for other problems on the same host, then logs in to see what is going on. Each step is simple, and it repeats on every page.
This guide connects Zabbix to Akmatori, an open-source, self-hosted AIOps agent. A webhook media type sends every problem to Akmatori, and an agent does the first investigation with the Zabbix API and read-only SSH before a human looks at it.
How It Works
- A Zabbix action sends the problem to a webhook media type that posts JSON to Akmatori.
- Akmatori normalizes the fields:
alert_namefrom the trigger name, the numeric severity,hardwareas the target host,metric_nameandmetric_valuefrom the item, andrunbook_urlfrom the trigger URL. Extra fields you add are kept with the alert. - Problems on the same host that belong together join one incident.
- The agent reads your runbooks and past incidents, then queries Zabbix and the host.
- You get a summary on the incident page and in Slack. When Zabbix sends the recovery, Akmatori marks the alert resolved.
Step 1: Create the Alert Source
In Akmatori, open Connectors, choose Zabbix, open the Alerts tab and create a source. Copy the webhook URL and set a secret. The Zabbix integration page has the full script.
Step 2: Create the Webhook Media Type
In Zabbix, go to Alerts > Media types > Create media type (in older versions, Administration > Media types). Choose type Webhook and add these parameters:
| Parameter | Value |
|---|---|
url |
your Akmatori webhook URL |
webhook_secret |
your secret |
event_time |
{EVENT.DATE} {EVENT.TIME} |
trigger_name |
{TRIGGER.NAME} |
trigger_severity |
{TRIGGER.SEVERITY} |
trigger_nseverity |
{TRIGGER.NSEVERITY} |
item_name |
{ITEM.NAME} |
item_value |
{ITEM.VALUE} |
trigger_expression |
{TRIGGER.EXPRESSION} |
event_age |
{EVENT.AGE} |
event_id |
{EVENT.ID} |
host |
{HOST.HOST} |
event_status |
{EVENT.STATUS} |
trigger_url |
{TRIGGER.URL} |
Then paste the script:
var params = JSON.parse(value);
var req = new HttpRequest();
req.addHeader('Content-Type: application/json');
if (params.webhook_secret) {
req.addHeader('X-Zabbix-Secret: ' + params.webhook_secret);
}
var response = req.post(params.url, JSON.stringify({
event_time: params.event_time,
alert_name: params.trigger_name,
severity: params.trigger_severity,
priority: params.trigger_nseverity,
metric_name: params.item_name,
metric_value: params.item_value,
trigger_expression: params.trigger_expression,
pending_duration: params.event_age,
event_id: params.event_id,
hardware: params.host,
event_status: params.event_status,
runbook_url: params.trigger_url
}));
if (req.getStatus() !== 200) {
throw 'Akmatori returned ' + req.getStatus() + ': ' + response;
}
return 'OK';
The status check at the end makes failed deliveries visible in the Zabbix action log instead of failing silently.
Step 3: Add a User and an Action
Assign the media type to a user (for example akmatori-bot) and create a trigger action that sends to that user. Start with a condition such as Trigger severity is greater than or equal to High, and enable Recovery operations so the recovery reaches Akmatori too.
Step 4: Connect Zabbix as a Tool
The webhook delivers problems. For the agent to investigate, also enable the Zabbix tool connector with an API token (or a user and password) for a read-only Zabbix user. The agent then uses:
| Question | Tool |
|---|---|
| Which other problems are open on this host? | zabbix.get_problems |
| What did the item do in the last hours? | zabbix.get_history |
| What exactly does this trigger check? | zabbix.get_triggers, zabbix.get_items |
| Which hosts are in the same group? | zabbix.get_hosts |
| What is happening on the host right now? | ssh.execute_command (read-only by default) |
SSH runs in read-only mode unless you allow write commands for a host, and any change becomes a proposal that a human must approve.
Two Zabbix-Specific Traps
Host name versus visible name. {HOST.HOST} is the technical host name, and {HOST.NAME} is the visible name. Send the one that matches your SSH inventory. If Zabbix says db-prod-03 (primary) and your SSH connector knows db-prod-03.int, the agent can read Zabbix data but cannot reach the host. If the names differ, add a field with the right value and change the alert source field mapping for the target host.
Triggers without context. A trigger named High load with no URL gives the agent little to start with. Put a link to your runbook in the trigger URL field: the script sends it as runbook_url, and the agent reads your runbooks before it touches infrastructure. Write trigger names that say what and where, such as Disk /var above 90% on {HOST.NAME}.
Choosing a Model
Zabbix teams often run on-premises for a reason, and that usually applies to the model too. Akmatori works with OpenAI, Anthropic and Google, and with any OpenAI-compatible endpoint you host yourself. SRE Bench compares models on 12 real incidents; for the on-premises options, see self-hosted AI SRE with local models.
Conclusion
Zabbix finds the problem. An agent connected to the Zabbix API and to the host can do the first round of "what else is wrong here, and what changed" in the minutes before a human arrives. Send the right host name, link a runbook in the trigger URL, give the agent a read-only Zabbix user, and enable recovery operations. If you also run Prometheus, the same pattern works with Alertmanager.
If your team wants AI-assisted incident workflows on your own infrastructure, Akmatori helps SRE teams investigate alerts, coordinate response, and automate safe infrastructure actions. Powered by Gcore for global infrastructure reliability.
