Alerts

13 alert types, 6 channels (ntfy, Discord, Telegram, webhook, stdout, log), per-agent overrides.

TokenJam fires alerts when something noteworthy happens: your agent crosses a budget threshold, calls a sensitive tool, retries in a loop, or drifts from its baseline. Alerts are evaluated locally as spans land in DuckDB and dispatched to one or more channels.

Alert types

TypeFires when
sensitive_actionA tool you marked as sensitive is invoked.
cost_budget_dailyDaily cost crosses the limit.
cost_budget_sessionA single session crosses the per-session limit.
session_durationA session runs longer than a threshold.
retry_loopA tool is retried with the same arguments N+ times.
token_anomalyToken usage deviates from baseline by N+ standard deviations.
schema_violationA tool output fails JSON Schema validation.
drift_detectedStatistical drift detected vs the agent’s baseline.
failure_rateTool error rate exceeds a threshold over a window.
network_egress_blockedNemoClaw sandbox blocked an outbound request.
filesystem_access_deniedNemoClaw sandbox blocked a file operation.
syscall_deniedNemoClaw sandbox blocked a syscall.
inference_reroutedNemoClaw rerouted inference to a different model.

Channels

Configure where alerts go. Multiple channels work simultaneously.

# ~/.config/tj/config.toml

[[alerts.channels]]
type = "ntfy"
topic = "my-agent-alerts"   # push to your phone, free, no account

[[alerts.channels]]
type = "discord"
webhook_url = "https://discord.com/api/webhooks/..."

[[alerts.channels]]
type = "telegram"
bot_token = "..."
chat_id   = "..."

[[alerts.channels]]
type = "webhook"
url = "https://your-endpoint.com/alerts"

[[alerts.channels]]
type = "stdout"

[[alerts.channels]]
type = "log"
path = "~/.config/tj/alerts.log"

Cooldowns

To avoid storms, each alert type has a cooldown:

[alerts.cooldowns]
cost_budget_daily = "1h"
retry_loop        = "5m"
drift_detected    = "24h"

Alerts fire once per cooldown window per agent. Override per agent under [agents.<id>.alerts.cooldowns].

Content stripping

Alert payloads can include prompt/completion content. Strip them globally:

[alerts.content]
include_prompts     = false
include_completions = false
include_tool_args   = false

When stripped, alerts contain only metadata: agent, model, cost, span ID, alert type, and severity. The full span is still available in DuckDB.

Acknowledgement

Alerts persist in DuckDB with an acknowledged_at timestamp. Acknowledge from the CLI, web UI, or MCP server (acknowledge_alert tool). Acknowledged alerts stop firing for that cooldown window.