Voice
Plugin Discord Activity
Shows live tool-call status as a Discord message that is updated and deleted when the agent finishes.
Install
npm install
pnpm
Configuration Example
"skillLearnedNotice": {
"model": "bifrost/gpt-6-luna",
"promptAppend": "Write the message in Traditional Chinese as used in Taiwan."
}
README
# Discord Activity Plugin for OpenClaw
[](https://clawhub.ai/wei840222/plugins/discord-activity)
[](https://opensource.org/licenses/MIT)
Discord Activity is an OpenClaw plugin that shows live agent and tool activity in Discord. For each Discord conversation, it creates one ANSI-colored status message, edits that message as tools run, folds in internal `skill-harness` and Hindsight recall status, then removes the status message after the agent finishes.
## Why this exists
When an OpenClaw agent is working from Discord, long-running tool calls can otherwise look like silence. This plugin gives users and operators a lightweight progress view without changing the final assistant reply.
It helps answer:
- Is the agent currently using tools?
- Which tool or internal pipeline phase is running?
- Did a tool complete, fail, or get reconciled after arriving before a Discord session existed?
- How long did completed tools take?
- Are internal companion workflows such as `skill-harness` and Hindsight still running?
The plugin is designed to fail open: if Discord credentials are missing or Discord API calls fail, it logs the problem and skips status updates instead of blocking the agent flow.
## What it shows
Status messages are Discord ANSI code blocks. The latest non-empty `progress_card` is pinned first, internal subagent groups follow, normal tools come next, and a main-agent failure appears last when present.
### Example display
Colored tool field labels use a single space before the green value, without a
separator colon. Colons inside field names and values are preserved. Plain context
rows and internal workflow details retain their own formatting.
A simplified live status message looks like this:
```ansi
π‘ skill-harness βΎ β [450ms]
βΉ 2 skills selected: handoff, hindsight-docs (.92)
π web_search βΎ β [450ms]
β°β query OpenClaw plugin SDK
```
`decision_evaluate` uses a dedicated `βοΈ` display with the same cyan header,
magenta result labels, green result values, and yellow timing as ordinary tools. It
shows each question's `instructions` (or its ID when omitted) and the input
criteria descriptions alongside the returned probabilities:
```text
βοΈ decision_evaluate βΎ β [952ms]
β‘ context: Reviewing an incoming support request.
β‘ detail: {"channel":"support","message":"Checkout is unavailable"}
Β» Should this message receive a reply?
ββ true Direct question or mention β 82.0%
β°β false No reply needed β 18.0%
Β» Which department should handle this? β support
ββ support Technical issues β 80.0%
β°β billing Payments and refunds β 20.0%
Β» How urgent is this? β score 1.70 / 2
ββ 0 Normal operation β 10.0%
ββ 1 Partial disruption β 10.0%
β°β 2 Service unavailable β 80.0%
```
Boolean false probability is calculated as `1 - probabilityTrue`. Choice
alternatives and score criteria retain input order. Scores display the provider's
score rounded to two decimal places against `criteria.length - 1`; probabilities
remain a separate distribution. Missing/null/blank descriptions show
`ζͺζδΎζθΏ°`; object and array instructions/descriptions display as JSON.
While running, results show `ηεΎ
η΅ζβ¦`. Missing or invalid results show
`η΅ζζͺζδΎ`, and unavailable outcomes show their reason without probabilities.
Shared `state` appears above the questions as flat `β‘ field: value` rows in input
order, without a state container. A JSON object string is parsed once and rendered
like object state, with each top-level field trimmed independently. Invalid JSON,
JSON arrays and JSON primitives keep their original string display; nested strings
are not parsed again. These rows use Discord's default text color,
matching skill-harness details; omission hints are light gray. Newlines and adjacent indentation
inside string values, including nested objects and arrays, become one space
before JSON serialization. Each combined `field: value` uses the ordinary-tool
70-code-point limit, including the field name, colon and space, with the same
`... (+N chars)` omission hint. The indent, `β‘` marker and omission suffix are
outside this limit; long field names are truncated too. String or array state appears directly
after `β‘`; absent/null/blank state and empty fields are omitted, while zero and
false field values remain visible.
Question headings use a yellow `Β»` and yellow instructions (or question ID),
while selected choices, scores and answer rows keep their result colors.
State markers, question markers and answer tree connectors all use four-space
indentation. Narrow Discord windows can still wrap lines.
The display omits model, provenance and token usage. Sanitization, result parsing
and monotonic message bounding rules are unchanged. Other tools
keep their existing display.
Status markers:
- `βΎ` details are expanded.
- `βΈ` details were collapsed to fit the message.
- `β` pending or currently visible as the latest non-final completed entry.
- `β` completed.
- `β` errored.
- `β»οΈ` orphan-reconciled after the tool result arrived before the Discord session was known.
Rendering rules to preserve:
- The latest `progress_card` tool call is rendered as one protected `π progress` block above every activity entry instead of appearing as an ordinary tool. Its Markdown note is flattened into a plain-text summary on a separate non-bold blue line below the bold cyan tool-style header, with formatting markers, links, raw HTML, and line breaks removed; a leading `<progress aria-label="β¦">` contributes a compact label when no plan exists, and every valid plan step remains ordered with `β` completed, `β` in progress, or `Β·` pending. A later empty card clears the block. Under the hard message limit, ordinary blocks are collapsed/removed before the progress note is compacted; plan steps remain visible whenever the protected content can fit.
- Normal tools render after `skill-harness` and Hindsight groups.
- `skill-harness` and Hindsight group order is stable.
- Each top-level tree connector starts under the second text character after the header emoji and separating space. Nested connectors and multiline continuation text likewise start under the second text character of their parent text.
- `skill-harness`, Hindsight, and the main-agent failure share one style that reads apart from ordinary tools. Their headers are bold blue, like `π progress`, while tool headers are bold cyan. Their detail lines use no tree connectors: each starts with `βΉ` at the same indent in Discord's default text color, and error lines use the same mark and alignment with both the mark and text in red. Detail fields with no visible text after sanitizing (for example only control or escape codes) are omitted. Current `skill-harness` and Hindsight producer events retain distinct errors as flat red `βΉ message β` rows, followed by only the latest progress or success message. Each new progress/result replaces that bottom row; without errors there is just one row. Hindsight uses accepted event order, including completions of earlier recalls. A group that recovers (`β»οΈ`) uses this same flat layout for legacy child entries too. The header's `β` / `β` / `β` already states progress, so `status`, `result`, and `error` values are shown without their key; any other field keeps `key: value`, and fields on one row stay joined with `Β·`. Truncation hints stay gray. Legacy child-only input can still render phase details before recovery; current producers do not create nested phases. Multiline values continue under the text after the mark.
- A failed main agent renders once as `π₯ agent β` at the bottom, with its error as a red line below it. It occupies one slot in the shared 6-entry budget and is protected from normal block removal.
- `skill-harness` keeps one current message from the fixed `status` / `result` fields and a separate error history. During pipeline execution the bottom message shows phase status and confidence (`(.xx)`); on completion it shows selected skills with confidence.
- The `skill-harness` status follows its explicit lifecycle: it remains `β` while running, including after a phase fails, and changes to `β` on `pipeline:completed`, or `β»οΈ` if errors were retained. A phase failure preserves the last progress message and candidate metadata so later phases can continue. `pipeline:failed` or unobserved completion renders `β` with error text.
- Tool-provided durations take precedence. When a completion omits `durationMs`, elapsed time falls back to the first observed `before_tool_call`; duplicate terminal events preserve that value instead of recalculating it.
- The `skill-harness` group duration comes directly from the producer's terminal parent lifecycle event. Individual phase durations still fall back to locally observed start/completion timing when the event does not provide `durationMs`.
- Durations up to and including 1000ms render in milliseconds. Durations above 1000ms and under 10 seconds round to at most two decimal places; durations of 10 seconds or more round to at most one decimal place. Trailing fractional zeros and a leftover decimal point are omitted.
- Status output keeps up to 3 child entries independently inside each of the `skill-harness` and Hindsight groups. Internal groups, normal tools, and a main-agent failure share one 6-entry outer budget; the failure uses the last slot when present. Older eligible blocks are removed from the top without mutating retained `toolHistory`.
- Every visible field keeps at most 70 Unicode code points after sanitization and serialization. Truncated values append an exact gray `(+N chars)` hint (`char` when singular) without splitting surrogate pairs. Producer field order and supplied line breaks are preserved within that fixed prefix; the renderer does not add hard wraps.
- Compact metadata rows pack any single-line fields whose total formatted width (key
... (truncated)
voice
Comments
Sign in to leave a comment