AI Insights & In-UI Assistant¶
Two AI features share one Anthropic API key:
- ai-insights (
shared/modules/ai-insights/) — a small container that periodically pulls latency/loss/microcut aggregates from InfluxDB, asks Claude for a plain-language network health report, and writes it as Markdown into a sharedreportsvolume. - web-admin AI pages (
/ai/reportsand/ai/chat) — the web UI renders the generated reports and offers an assistant chat that can inspect stats and (with your confirmation) manage targets.
Both are optional: without ANTHROPIC_API_KEY the ai-insights container
logs a notice and exits cleanly, and the web-admin AI pages render a
"not configured" explanation instead of erroring.
Enabling¶
- Get an API key from https://console.anthropic.com/ .
- On the Pi, set it. It is asked for at a prompt, never typed on the command line, and only the services that read it are recreated:
sudo smoking-pi config set ANTHROPIC_API_KEY
- Turn on the
aiservice, keeping the others as they are:
sudo smoking-pi enable ai
A new install can choose it directly: sudo smoking-pi install
--profiles ai.
Optional settings, each with sudo smoking-pi config set KEY VALUE:
| Key | Default | What it does |
|---|---|---|
AI_MODEL |
claude-haiku-4-5-20251001 |
The model that writes reports and answers chat |
REPORT_INTERVAL |
86400 |
Seconds between reports (daily) |
AI_REPORTS_PER_DAY |
8 |
Hard cap on report API calls per day |
AI_MAX_INPUT_CHARS |
20000 |
Prompt-size guardrail |
From a clone or a package alike: sudo smoking-pi config set
ANTHROPIC_API_KEY (asked for, never on the command line), then
sudo smoking-pi enable ai, which records the profile so every later
down and up keeps the service.
What the reporter does¶
Once per REPORT_INTERVAL (daily by default) the container:
- Queries InfluxDB for the last 24 h: per-target median/p95 latency,
mean/max packet loss, count of >=5 % loss samples (from
latencyanddns_latency, converting seconds→ms and loss ratio→percent), plus a CPE microcut summary fromcpe_latency(loss already 0–100 %). - Renders a compact text summary — capped at the worst ~30 targets by loss
and truncated at
AI_MAX_INPUT_CHARS— and sends it to Claude with a fixed "network health analyst" system prompt. - Writes
report-YYYYMMDD-HHMMSS.mdand refresheslatest.mdunder/reports. web-admin lists and renders these at AI → Reports.
The in-UI assistant¶
AI → Assistant in web-admin is a chat backed by the same Claude model.
It has read tools (list targets, latency stats, loss events, microcut stats,
system status, diagnose_loss, get_incident_history,
get_notification_history) that run
immediately, and mutating tools (add/remove/toggle target) that are never
executed directly — the UI shows a confirmation
card and only executes after you approve. Config regeneration happens
automatically on target changes, so there is no apply_config tool.
The loss-event threshold and the definition of a microcut are the shared
ones (common/aggregates.py, common/microcuts.py), the same code the MCP
server, the alerter and the reports read — see
Detection reliability. get_microcut_stats
answers with cuts and their durations plus the gateway's loss floor, and
get_loss_events counts two or more lost pings as an event (15% on a
10-ping probe, whatever the probe sends), so the in-UI
assistant and the OpenClaw one say the same thing about the same night.
It is told how to answer by the same guide every MCP client and the
OpenClaw skill get (shared/modules/common/guide.py), after a short header
of its own: target changes need a confirmation, and tools the guide names
that this chat lacks (get_chart, get_wifi_stats, the mute and ack
tools) are pointed to Grafana instead. diagnose_loss and
get_incident_history answer through common/incident_answers.py, and
get_notification_history through common/notification_ledger.py (the
alerter's state volume, mounted read-only), the MCP server's own code
paths, and the compose file gives web-admin the same
WIDESPREAD_PCT / VERDICT_BROAD_PCT / WIFI_WEAK_* thresholds. Until
2026-10-13 the chat had a two-sentence prompt of its own and no diagnosis:
it read raw loss events and attributed them itself, so it could still call
the Pi's hung radio an outage after every other assistant had stopped.
Responses are non-streaming (Haiku answers small tool-augmented prompts in a couple of seconds), and the conversation history lives in the browser tab — reloading the page starts a fresh conversation.
Cost expectations¶
The default model is Claude Haiku 4.5 (about $1 per million input tokens,
$5 per million output tokens). A daily report consumes roughly 2–4 k input
tokens and <1 k output tokens — around a tenth of a cent per report, i.e.
pennies per month. The chat costs more per question: every model round
resends the shared guide and the tool list (about 4.6 k input tokens before
the conversation itself), and a question that calls two or three tools
takes three or four rounds, so expect one to two cents per question, more
for a week-long diagnose_loss (up to 50 incidents with their evidence).
The AI_REPORTS_PER_DAY cap (default 8) bounds the reporter even if it is
misconfigured to run in a tight loop.
Environment variables¶
| Variable | Default | Used by | Meaning |
|---|---|---|---|
ANTHROPIC_API_KEY |
(unset — AI disabled) | both | Anthropic API key |
AI_MODEL |
claude-haiku-4-5-20251001 |
both | Claude model ID |
REPORTS_DIR |
/reports |
both | Report directory (rw for ai-insights, ro for web-admin) |
REPORT_INTERVAL |
86400 |
ai-insights | Seconds between reports in --loop mode |
REPORT_WINDOW_HOURS |
24 |
ai-insights | Lookback window per report |
AI_REPORTS_PER_DAY |
8 |
ai-insights | Daily report cap (state file in REPORTS_DIR) |
AI_MAX_INPUT_CHARS |
20000 |
ai-insights | Prompt-size cap (truncated with a note) |
INFLUX_URL / INFLUX_TOKEN / INFLUX_ORG / INFLUX_BUCKET |
see compose | both | InfluxDB 2.x connection |