aiagent/skill/embedded/builtin/host-health-diagnose/SKILL.md
Enter this skill:
Do NOT enter this skill:
creation / troubleshootingresource_querytroubleshootingA diagnosis that concludes from a single layer of evidence is almost always wrong.
When n9e shows a machine as unreachable, it may stem from:
The "recommended action" for these five conclusions is completely different. So gather evidence first, then classify, and give the action last.
get_target_realtime_status(ident)Reads Redis to get:
beat_time / lag_seconds — seconds since the most recent heartbeatstatus — active(<60s) / lagging(60–180s) / stale(≥180s) / stale_no_heartbeat(no such key in Redis)offset — clock skew between agent and server (an abnormally large value usually means the agent clock has drifted / NTP is broken)cpu_util / mem_util — resource usage from the most recent reportagent_version / remote_addr / extend_infoKey judgments:
status=stale_no_heartbeat while update_at_db is several days ago — the agent has never connected, a deployment problem.status=stale_no_heartbeat while update_at_db is a few minutes ago — the Redis layer is down or has been cleared.status=stale while the last reported cpu_util / mem_util was low — possibly a graceful exit (shutdown / kernel reclaim after OOM), leaning toward "truly down".status=stale while the last reported cpu_util was high (>90%) — leaning toward "agent hung / host hang".offset > 30s — not necessarily down, but the agent clock has a problem and will throw off alert evaluation, so flag it separately.query_host_metrics_window(ident)By default queries cpu_usage_active / mem_available_percent / system_load1 / net_bytes_recv / net_bytes_sent. Returns samples_count / first_ts / last_ts / min / max / avg / last for each metric.
Key judgments:
samples_count=0 and series=0 — the Prom layer has no data at all. If it stops at the same moment as BeatTime → heartbeat and metrics share the same source (categraf), and stopping together means the agent really is not sending; stopping at different moments means the data flow was cut by different stages.last_ts far earlier than now — metrics have also stopped; compare with BeatTime to see whether the stop times match.samples_count > 0 but BeatTime is already stale — a typical agent hang or Redis write latency: the metric stream is still flowing (the categraf main process is sending), but the heartbeat cannot be written to Redis.cpu_usage_active.last > 95% + system_load1.last far above cpu_num — a strong signal of host hang.net_bytes_recv.last + net_bytes_sent.last close to 0 — the NIC is silent; combined with a stopped BeatTime this points to "truly down" or "network cut".⚠️ By default, if datasource_id is not passed, the chat-level datasource is used as a fallback; when the user has not selected a datasource in the frontend, first list_datasources and pick a Prom datasource.
list_neighbor_targets(ident)Pulls other machines in the same business group (target.GroupIds), returning items + summary{total, active, lagging, stale}.
Key judgments:
list_alert_mutes / get_alert_mute_detail — matched a mute rule → the "under maintenance" branch; not a false positive, and tell the user when the mute window ends.search_active_alerts — check whether there are other companion alerts (cpu/mem/disk alerts for the same ident firing at the same time) → leans toward "the host is really in trouble".get_target_detail — check update_at (the most recent time a heartbeat was persisted at the DB layer). If update_at is newer than Redis's beat_time, the Redis layer has been cleared; the reverse means the DB layer is stuck.| Signal combination | Conclusion | Confidence |
|---|---|---|
| BeatTime stale + metrics also stopped (last_ts ≈ beat_time) + neighbors mostly active + last cpu/mem is low | Truly down | High |
| BeatTime stale + metrics also stopped + multiple machines in the same business group stale at once | Cluster event (not a single-machine outage; guide them to investigate upstream) | High |
| BeatTime stale + metrics still moving (samples_count > 0 and last_ts close to now) | Agent hung / Redis heartbeat channel anomaly | High |
| BeatTime lagging 30–180s + a few neighbors lagging in sync | Network flapping / brief partition, will most likely self-heal | Medium |
| Matched a mute / maintenance window | Under maintenance | High |
| BeatTime stale + last cpu_util > 95% / load spiking + neighbors normal | Host hang (CPU at 100%, IO stuck, kernel softlockup), counts as "down in a broad sense" but the recommended direction differs | Medium |
| None of the above match | Insufficient data; honestly say "cannot determine", and list the evidence already collected so the user can fill in the gaps | — |
Final Answer in Markdown, in the user's language. Four sections:
## Conclusion
<one sentence: truly down / agent hung / network flapping / under maintenance / cluster event / insufficient data, cannot determine>
## Key Evidence
- Heartbeat: beat_time=2026-05-14 10:23:11, lag=312s, status=stale; db update_at=...
- Metrics (10m): cpu_usage_active recent last=0.5% (steadily declining from first to last value), net_bytes_sent last=0 — metric stream and heartbeat stopped at the same time
- Neighbors: same business group 18/20 active, only this machine stale
- Mute: not matched
## Recommended Actions
1. <the thing to do first>
2. <next best>
3. <if you want to self-verify, do it this way>
## False-Positive Risk
<under what circumstances this conclusion would not hold, e.g. "if there was a recent cleanup operation on the Redis layer, this judgment does not hold">
BeatTime field. Always pull the metric window and neighbors for cross-validation.query_prometheus to pull back a long string of raw time-series points and blow up the token budget. query_host_metrics_window already compresses by "min/max/avg/last"; see whether the aggregate is enough before deciding whether to look at the detail.systemctl status categraf / ps -ef | grep categraf / journalctl -u categraf --since "5 min ago").