Skip to main content
Triage is Volvox.Bot’s proactive conversation engine. Rather than waiting to be mentioned, the triage system continuously buffers channel messages and evaluates them in batches. A lightweight classifier decides whether to engage; a more capable responder generates the reply only when needed.

How it works

1

Messages accumulate in a buffer

Incoming messages are added to a per-channel ring buffer (up to maxBufferSize messages). Each buffer entry includes the author, content, timestamp, and — if the message is a reply — the referenced message.
2

Evaluation is triggered

A dynamic timer fires after defaultInterval milliseconds of inactivity. If the buffer has more messages, the interval is shortened. If a configured trigger word is detected, evaluation is forced immediately.
3

Haiku classifies the batch

The classifier (claude-haiku-4-5 by default) reads the buffer snapshot and returns one of: respond, chime-in, moderate, or ignore. Around 80% of evaluations result in ignore, which means Sonnet never runs for that batch.
4

Sonnet generates the response

When the classification is not ignore, the responder (claude-sonnet-4-6 by default) generates a reply targeted at the relevant messages. It can use the WebSearch tool and will signal this with a 🔍 reaction on the trigger message.
5

Response is sent and memories are extracted

The bot replies to the relevant messages. If debug footer is enabled, an embed with token and cost stats is attached. In the background, user memories are extracted and stored for future context.
The bot always overrides an ignore classification when it is directly @mentioned in one of the buffered messages.

Trigger words

Trigger words cause an immediate evaluation regardless of the timer. When any message in the buffer contains a trigger word, evaluateNow() fires without waiting.
"triage": {
  "triggerWords": ["volvox"]
}
If the forced evaluation fails, the bot falls back to the normal scheduled timer.

Daily budget

Set dailyBudgetUsd to cap how much the triage system spends per day per guild. Once the cap is reached, evaluations are paused until the daily window resets. A throttled alert (at most once per hour) is posted to moderationLogChannel when the cap is hit.
"triage": {
  "dailyBudgetUsd": 10
}
Set to 0 or omit the key to disable the budget gate.

Channel inclusion and exclusion

Control which channels participate in triage:
"triage": {
  "channels": [],
  "excludeChannels": []
}
Config keyBehavior
channelsAllowlist — if non-empty, only these channel IDs are evaluated. An empty array means all channels.
excludeChannelsDenylist — these channel IDs are always skipped, even if listed in channels.
Exclusion takes precedence over inclusion. Channels in ai.blockedChannelIds are also excluded from triage.

Moderation response mode

When the classifier returns moderate, the responder generates a moderation-appropriate message and posts a structured embed to moderationLogChannel.
"triage": {
  "moderationResponse": true,
  "moderationLogChannel": "1473219285651292201"
}
Set moderationResponse to false to suppress in-channel responses for moderation events while still logging to the mod channel. The moderation log embed includes the recommended action (warn, timeout, kick, ban, or delete), the violated rule, the channel, and the flagged message content. Protected role members (admins, moderators) are skipped automatically.

Streaming

By default, triage uses non-streaming mode — the responder waits for a complete response before sending anything to Discord. Enable streaming to start sending partial output as it arrives.
"triage": {
  "streaming": false
}
When debugFooter is true, each triage response includes an embed showing per-invocation AI usage stats.
"triage": {
  "debugFooter": true,
  "debugFooterLevel": "verbose"
}
The footer includes token counts, cost estimates for both the classifier and responder steps, and the number of web searches performed.

Status reactions

The bot adds emoji reactions to the trigger message to signal what stage of evaluation it is in:
EmojiMeaning
👀Classification in progress
💬Generating a response
🧠Generating a response with thinking tokens enabled
🔍Web search in progress (stays after response is sent)
Disable status reactions by setting statusReactions to false.

Full config reference

"triage": {
  "enabled": true,
  "defaultInterval": 3000,
  "maxBufferSize": 30,
  "triggerWords": ["volvox"],
  "moderationKeywords": [],
  "classifyModel": "claude-haiku-4-5",
  "classifyBudget": 0.05,
  "respondModel": "claude-sonnet-4-6",
  "respondBudget": 0.2,
  "thinkingTokens": 1024,
  "classifyBaseUrl": null,
  "classifyApiKey": null,
  "respondBaseUrl": null,
  "respondApiKey": null,
  "streaming": false,
  "tokenRecycleLimit": 20000,
  "contextMessages": 10,
  "timeout": 30000,
  "moderationResponse": true,
  "channels": [],
  "excludeChannels": [],
  "debugFooter": true,
  "debugFooterLevel": "verbose",
  "moderationLogChannel": "1473219285651292201",
  "statusReactions": true,
  "dailyBudgetUsd": 10
}
Config keyDefaultDescription
enabledtrueEnable or disable the triage system
defaultInterval3000Base evaluation timer in milliseconds
maxBufferSize30Maximum messages held per channel buffer
triggerWords["volvox"]Words that force an immediate evaluation
classifyModelclaude-haiku-4-5Model used for the classifier step
classifyBudget0.05Per-invocation spend cap for the classifier (USD)
respondModelclaude-sonnet-4-6Model used for the responder step
respondBudget0.2Per-invocation spend cap for the responder (USD)
thinkingTokens1024Extended thinking token budget for the responder (0 to disable)
streamingfalseStream partial response output to Discord
tokenRecycleLimit20000Token count at which the CLI process is recycled
contextMessages10Number of historical messages fetched from Discord for context
timeout30000Evaluation timeout in milliseconds
moderationResponsetrueSend in-channel responses for moderation classifications
channels[]Allowlisted channel IDs (empty = all channels)
excludeChannels[]Denylisted channel IDs
debugFootertrueAttach an AI usage stats embed to responses
debugFooterLevelverboseFooter detail level (verbose or compact)
moderationLogChannelChannel ID for moderation audit embeds and budget alerts
statusReactionstrueAdd emoji reactions to show evaluation progress
dailyBudgetUsd10Daily spend cap per guild in USD (0 to disable)

Build docs developers (and LLMs) love