Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Retrieve polled metric history from Zabbix — interface utilization, counters and any collected item — over any time window, correctly routed between raw history and hourly trends. Use when someone asks what something WAS doing over time: is this normal, what did this interface do overnight, was it like this last Tuesday. This is the only NetClaw skill that can answer a question about the past from a poller.
.claude/skills/automateyournetwork-zabbix-metrics-history/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 10% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 2% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-04 | ✓→✗ | ▼ Worse | -29% | 0% |
zabbix-mcp — vendored third-party (mpeirone/zabbix-mcp-server, GPL-3.0, pinned 0722f48), running from its own virtualenv. Three tools: zabbix_api(method, params), zabbix_api_docs(method), zabbix_api_list(object). Read-only, enforced two ways (forced flag + destructive-method deny-list).
This server is a generic passthrough. It will not stop you getting a wrong answer.
Unlike most NetClaw integrations, there is no code between you and the API enforcing correctness. Zabbix has two traps that return an empty array and a success status — no error, no warning. If you skip the procedure below you will confidently tell an engineer an interface was idle when it was carrying traffic.
Follow the procedure. It is the only safeguard that exists.
item.get FIRST. Never call history.get without it.jsonczabbix_api("item.get", { "hostids": ["<hostid>"], "search": {"key_": "net.if.in"}, // or whatever you're after "output": ["itemid","name","key_","value_type","units","history","trends"] })
You need four fields off every item:
| Field | Why | |---|---| | value_type | Step 2 depends on it. Getting it wrong returns empty, silently | | history | how far back raw values exist — or 0, meaning never stored | | trends | how far back hourly aggregates exist — or 0, meaning none | | units | so your answer has units |
value_type. Do not accept the default.history.get defaults history to 3 (numeric unsigned). Measured on a stock Zabbix 7.0: 84 of 121 items are 0 (float). So the default is wrong for most items, and wrong silently.
| value_type | Meaning | |---|---| | 0 | float ← most interface counters and rates | | 1 | character | | 2 | log | | 3 | unsigned ← the API default | | 4 | text | | 5 | binary |
jsonczabbix_api("history.get", { "itemids": ["<itemid>"], "history": 0, // ← the item's OWN value_type, not the default "time_from": <epoch>, "time_till": <epoch>, "output": "extend", "sortfield": "clock", "sortorder": "DESC", "limit": 500 })
A single history.get serves one value type. Query four items of mixed types and you get back only the matching ones — the rest vanish with no error. Measured: 2 of 4 returned each way, zero overlap.
Group your items by value_type, make one call per group, merge the results.
Raw history is short-lived; hourly aggregates last far longer. item.get told you both in Step 1.
| Requested window | Use | Say in your answer | |---|---|---| | entirely within history | history.get | raw polled values | | entirely beyond history, trends > 0 | trend.get | hourly min/avg/max, not instantaneous | | spans the boundary | both, merged | which part came from which | | beyond both | neither exists | not retained — see below |
trend.get returns value_min / value_avg / value_max / num per hour, and is numeric only.
Say when you used trends. "The peak was 400 Mbps" from raw values and from an hourly average are different claims, and an engineer sizing a link needs to know which they have.
They are indistinguishable over the wire — all five are an empty array. Tell them apart, and word them differently.
| Cause | How to tell | How to say it | |---|---|---| | Wrong value type | you didn't do Step 1/2 | Never report this. Re-query correctly | | Aged out | window predates history, trends > 0 | "beyond raw retention — here is the hourly data" | | Retention disabled | history=0 and/or trends=0 on the item | "this item does not retain that" — a configuration fact, not an absence | | Never collected | item exists, no values ever, empty lastclock | "monitored but has never returned a value" — a real finding, usually a broken poll | | Genuinely idle | data exists and the values are zero | "zero throughput" — the only one that means nothing happened |
Retention can be switched off per item. Measured on a stock install: 10 items had trends=0, and 5 had both history=0 and trends=0 — collected purely to fire triggers, never stored. Read the item; do not guess.
and the NMS is a likely cause, and surfacing the NMS time makes that diagnosable instead of baffling.
Refuse a future window or a reversed start/end with the reason — do not return empty.
If the same item key exists on multiple hosts, never merge them into one series without saying so.
| Want to… | Use | |---|---| | Receive unsolicited traps | snmptrap-mcp — that is push; this polls on an interval and keeps history | | Flow records | ipfix-mcp — flows, not counters | | Metrics from infrastructure you instrumented | prometheus, grafana — pull-based stores; this is the NMS for gear you did not instrument | | SaaS monitoring with its own agents | auvik, thousandeyes, datadog — this is the self-hosted NMS an enterprise already runs | | Current device state | pyats, multivendor-cli, fortinet — they read the device now; this answers what it was over time, and can answer for a device that is unreachable right now | | Problems and alerts | zabbix-problem-review | | Availability and inventory | zabbix-availability |
item.get before history.get. Always. There is no shortcut and nothing will catch you.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-19 | pass→pass | 15,791 | 13,830 | -12% | 1 | 1 | 0% | 2,454 | 3,834 | +56% | 0 | 0 | — |
case-01 | fail→fail | 23,296 | 13,470 | -42% | 1 | 1 | 0% | 2,894 | 2,273 | -21% | 0 | 0 | — |
case-02 | fail→fail | 20,639 | 12,741 | -38% | 1 | 1 | 0% | 3,189 | 2,165 | -32% | 0 | 0 | — |
case-03 | fail→fail | 16,946 | 17,495 | +3% | 1 | 1 | 0% | 2,156 | 2,247 | +4% | 0 | 0 | — |
case-04 | pass→fail | 20,011 | 12,552 | -37% | 1 | 1 | 0% | 3,653 | 2,593 | -29% | 0 | 0 | — |
case-05 | fail→fail | 13,663 | 13,872 | +2% | 1 | 1 | 0% | 2,012 | 2,260 | +12% | 0 | 0 | — |
case-06 | fail→pass | 18,825 | 29,888 | +59% | 1 | 1 | 0% | 3,161 | 3,857 | +22% | 0 | 0 | — |
case-07 | pass→pass | 4,284 | 9,441 | +120% | 1 | 1 | 0% | 803 | 2,684 | +234% | 0 | 0 | — |
case-08 | fail→fail | 17,126 | 7,647 | -55% | 1 | 1 | 0% | 2,447 | 2,370 | -3% | 0 | 0 | — |
case-09 | pass→pass | 9,783 | 6,439 | -34% | 1 | 1 | 0% | 1,379 | 2,927 | +112% | 0 | 0 | — |
case-10 | pass→pass | 16,417 | 12,532 | -24% | 1 | 1 | 0% | 2,717 | 2,900 | +7% | 0 | 0 | — |
case-11 | pass→pass | 11,390 | 5,383 | -53% | 1 | 1 | 0% | 1,487 | 2,544 | +71% | 0 | 0 | — |
case-12 | fail→fail | 6,710 | 22,774 | +239% | 1 | 1 | 0% | 868 | 2,680 | +209% | 0 | 0 | — |
case-13 | pass→pass | 8,706 | 6,815 | -22% | 1 | 1 | 0% | 1,376 | 3,199 | +132% | 0 | 0 | — |
case-14 | pass→fail | 9,619 | 7,078 | -26% | 1 | 1 | 0% | 1,552 | 2,200 | +42% | 0 | 0 | — |
case-15 | fail→fail | 13,210 | 7,687 | -42% | 1 | 1 | 0% | 1,918 | 2,301 | +20% | 0 | 0 | — |
case-16 | fail→pass | 11,993 | 5,648 | -53% | 1 | 1 | 0% | 2,441 | 2,686 | +10% | 0 | 0 | — |
case-17 | fail→fail | 9,901 | 7,303 | -26% | 1 | 1 | 0% | 1,928 | 2,187 | +13% | 0 | 0 | — |
case-18 | pass→fail | 13,646 | 7,292 | -47% | 1 | 1 | 0% | 1,839 | 2,304 | +25% | 0 | 0 | — |
case-20 | fail→pass | 19,075 | 11,917 | -38% | 1 | 1 | 0% | 3,434 | 3,497 | +2% | 0 | 0 | — |
case-21 | fail→fail | 6,079 | 9,791 | +61% | 1 | 1 | 0% | 1,087 | 2,364 | +117% | 0 | 0 | — |
case-22 | fail→pass | 22,329 | 7,100 | -68% | 1 | 1 | 0% | 2,307 | 2,818 | +22% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 11 counted toward the lift figure. The other 11 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +5 percentage points is the difference between those two pass rates over the 11 comparable cases. 6 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.