refactor: move transcripts into core

Move meeting notes into core transcripts, remove the bundled meeting-notes plugin/API, and require explicit transcripts.enabled before exposing the recording-capable tool.
This commit is contained in:
Peter Steinberger
2026-05-26 14:51:11 +01:00
committed by GitHub
parent 45feb37b13
commit cac0b2db18
94 changed files with 1008 additions and 1286 deletions

View File

@@ -42,7 +42,7 @@ Capabilities are the public **native plugin** model inside OpenClaw. Every nativ
| Realtime transcription | `api.registerRealtimeTranscriptionProvider(...)` | `openai` |
| Realtime voice | `api.registerRealtimeVoiceProvider(...)` | `openai` |
| Media understanding | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` |
| Meeting notes source | `api.registerMeetingNotesSourceProvider(...)` | `discord`, `meeting-notes` |
| Transcripts source | `api.registerTranscriptSourceProvider(...)` | `discord` |
| Image generation | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` |
| Music generation | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` |
| Video generation | `api.registerVideoGenerationProvider(...)` | `qwen` |

View File

@@ -649,7 +649,7 @@ Each list is optional:
| `realtimeVoiceProviders` | `string[]` | Realtime-voice provider ids this plugin owns. |
| `memoryEmbeddingProviders` | `string[]` | Memory embedding provider ids this plugin owns. |
| `mediaUnderstandingProviders` | `string[]` | Media-understanding provider ids this plugin owns. |
| `meetingNotesSourceProviders` | `string[]` | Meeting-notes source provider ids this plugin owns. |
| `transcriptSourceProviders` | `string[]` | Transcript source provider ids this plugin owns. |
| `imageGenerationProviders` | `string[]` | Image-generation provider ids this plugin owns. |
| `videoGenerationProviders` | `string[]` | Video-generation provider ids this plugin owns. |
| `webFetchProviders` | `string[]` | Web-fetch provider ids this plugin owns. |

View File

@@ -1,359 +0,0 @@
---
summary: "Meeting Notes plugin: capture transcripts from Discord voice and imported meeting sources, then write summaries"
read_when:
- You want OpenClaw to take meeting notes
- You are wiring Discord voice, Google Meet, Slack huddles, or another meeting source into notes
- You need the meeting_notes tool contract
title: "Meeting Notes plugin"
---
The Meeting Notes plugin is the generic notes layer for live calls and imported
meeting transcripts. It owns transcript storage, summary rendering, and the
`meeting_notes` tool. Channel plugins own capture, authentication, and
platform-specific meeting joins.
Use this page when you want OpenClaw to capture Discord voice notes today, when
you want to import a transcript from another meeting system, or when you are
building a Google Meet, Slack huddle, Zoom, or calendar-owned source provider.
## Source model
Meeting sources register `meetingNotesSourceProviders` through the plugin SDK.
The first live provider is `discord-voice`; the built-in `manual-transcript`
provider imports post-meeting transcripts.
- `live-audio`: source joins or listens to a call and streams final utterances.
- `live-caption`: source reads captions from a browser or meeting surface.
- `posthoc-transcript`: source imports a transcript or notes artifact after the meeting.
- `recording-stt`: source transcribes a recording before importing utterances.
This keeps Discord, Google Meet, Slack huddles, and future meeting surfaces out
of the notes engine. Each source supplies speaker-labeled utterances; Meeting
Notes writes the artifacts and summary.
## Install and enable
Meeting Notes is an external source plugin in this repository. It is not part of
the core OpenClaw npm package and becomes available only when the plugin is
installed as a plugin or loaded from a source checkout that contains
`extensions/meeting-notes`.
Once the plugin is loaded, it is enabled by default unless one of these settings
blocks it:
- `plugins.enabled: false` disables all plugins.
- `plugins.deny` contains `meeting-notes`.
- `plugins.allow` is set and does not contain `meeting-notes`.
- `plugins.entries.meeting-notes.enabled: false` disables this plugin entry.
- `plugins.entries.meeting-notes.config.enabled: false` keeps the plugin loaded
but disables the `meeting_notes` tool and auto-start service.
The normal user config file is `~/.openclaw/openclaw.json`. The `plugins`
section controls plugin loading, and the nested `entries.<pluginId>.config`
object is passed to that plugin as plugin-specific config. A separate
`config: { ... }` block under `meeting-notes` is expected; it is how plugins
receive their own options without adding core config keys.
Use this shape when your config has a plugin allowlist:
```json5
{
plugins: {
allow: ["discord", "meeting-notes"],
entries: {
"meeting-notes": {
enabled: true,
config: {
enabled: true,
maxUtterances: 2000,
autoStart: [],
},
},
},
},
}
```
Run a config check after editing:
```bash
openclaw config validate
```
Gateway config hot reload applies plugin allowlist and plugin-entry changes.
Restart the Gateway if you are also changing the source plugin itself, installing
new plugin files, or changing Discord voice credentials.
## Configuration
Meeting Notes has three plugin config fields:
- `enabled`: `true` by default. Set `false` to leave the plugin installed but
disable the tool and auto-start service.
- `maxUtterances`: `2000` by default. Summary generation reads only the newest
N utterances from `transcript.jsonl`; valid values are clamped to `1` through
`10000`.
- `autoStart`: empty by default. Each entry starts a live notes source when the
Gateway starts or reloads the plugin.
An `autoStart` entry accepts:
- `providerId`: required. Use `discord-voice` for Discord voice.
- `enabled`: optional, default `true`. Set `false` to keep an entry without
starting it.
- `sessionId`: optional. If omitted, OpenClaw generates a timestamped id.
- `title`: optional human-readable title for summaries and CLI output.
- `accountId`: optional source account id when more than one account exists.
- `guildId`: provider-specific Discord guild id.
- `channelId`: provider-specific Discord voice channel id.
- `meetingUrl`: provider-specific meeting URL for browser or calendar sources.
Use `autoStart` when OpenClaw should begin notes capture automatically on
gateway startup:
```json5
{
plugins: {
entries: {
"meeting-notes": {
config: {
autoStart: [
{
providerId: "discord-voice",
guildId: "123",
channelId: "456",
title: "Weekly planning",
},
],
},
},
},
},
}
```
Auto-start retries startup failures up to 12 times with a five-second delay.
This lets the notes service wait for channel plugins such as Discord to finish
initializing. Sessions that were started by auto-start are stopped and summarized
when the plugin service stops cleanly.
Discord voice capture still needs normal Discord voice setup and permissions.
See [Discord voice](/channels/discord#voice-mode).
## Discord voice
Discord is the first live source. The Discord plugin owns the voice connection,
speaker detection, audio decoding, and transcription. Meeting Notes receives
final speaker-labeled utterances and persists them.
For Discord live capture:
- Enable and configure the Discord plugin first.
- Configure Discord voice mode so OpenClaw can join the target voice channel.
- Use `providerId: "discord-voice"`.
- Provide `guildId` and `channelId`.
- Add `accountId` only when you run more than one Discord account.
The transcription model is not chosen by Meeting Notes. In Discord `stt-tts`
voice mode, STT uses `tools.media.audio`; `voice.model` controls the agent reply
model, not transcription. In realtime voice modes, transcription follows the
configured realtime provider and model. See [Discord voice](/channels/discord#voice-mode)
for the current Discord voice model and provider knobs.
## Google Meet, Slack huddles, and other sources
Meeting Notes is intentionally source-neutral. Google Meet, Slack huddles, Zoom,
calendar recordings, or browser caption capture should be separate source
providers that register with the plugin SDK.
Recommended source choices:
- Google Meet live browser/caption support: implement a `live-caption` provider
that accepts `meetingUrl` and emits final caption utterances.
- Google Meet recordings or downloaded transcripts: implement
`posthoc-transcript` or use `manual-transcript` until a provider exists.
- Slack huddles today: import post-meeting huddle notes or transcript artifacts.
Slack does not expose a general bot-join live huddle audio API.
- Slack huddles later: keep the Slack-owned source provider responsible for
Slack auth, artifact lookup, and transcript normalization.
The notes engine should not contain platform joins, browser automation, Slack
API polling, or Discord voice logic. Those belong to the owning source plugin.
## Tool
Use `meeting_notes` with an `action`:
- `status`: list registered providers and active sessions.
- `start`: start a live notes session.
- `stop`: stop a live session and write `summary.md`.
- `import`: import a transcript and write `summary.md`.
- `summarize`: regenerate a summary for an existing session.
Discord live notes require `providerId: "discord-voice"`, plus `guildId` and
`channelId`. `accountId` is optional when only one Discord account is active.
```json
{
"action": "start",
"providerId": "discord-voice",
"guildId": "123",
"channelId": "456",
"title": "Weekly planning"
}
```
Stop by session id:
```json
{
"action": "stop",
"sessionId": "meeting-2026-05-22T10-00-00-000Z-a1b2c3d4"
}
```
Import a transcript:
```json
{
"action": "import",
"providerId": "manual-transcript",
"title": "Design review",
"transcript": "Alex: We decided to ship the Discord source first.\nSam: Action item: add Slack huddle import later."
}
```
`manual-transcript` splits plain transcript text into utterances. Use it for
copied Google Meet notes, Slack huddle summaries, calendar transcripts, or any
source that already produced text.
## Storage layout
Artifacts are stored under the OpenClaw state directory:
```text
$OPENCLAW_STATE_DIR/meeting-notes/YYYY-MM-DD/<session>/
metadata.json
transcript.jsonl
summary.json
summary.md
```
If `OPENCLAW_STATE_DIR` is unset, the default state directory is
`~/.openclaw`. A normal local install therefore writes notes under
`~/.openclaw/meeting-notes/...`.
Each file has one job:
- `metadata.json`: session id, source provider, title, start time, stop time,
and provider metadata.
- `transcript.jsonl`: append-only speaker utterances. Each line is one JSON
object with the utterance text and the session id.
- `summary.json`: structured summary data used by tooling, including the
speaker-labeled transcript window used for the generated summary.
- `summary.md`: human-readable notes for terminals, editors, and document
workflows, including a speaker-labeled transcript section.
The date directory comes from the session start time, so multiple meetings per
day stay grouped. If a human session id repeats across days, use the
date-qualified selector from `openclaw meeting-notes list`, such as
`2026-05-22/standup`.
By default, OpenClaw generates timestamped session ids:
```text
meeting-2026-05-22T10-00-00-000Z-a1b2c3d4
```
That means ten meetings on the same day become ten sibling directories:
```text
~/.openclaw/meeting-notes/2026-05-22/
meeting-2026-05-22T09-00-00-000Z-a1b2c3d4/
meeting-2026-05-22T10-30-00-000Z-b2c3d4e5/
meeting-2026-05-22T13-00-00-000Z-c3d4e5f6/
```
Configure `sessionId` only when that id is unique for the day. Human ids such as
`standup` are fine for one recurring meeting per day. If the same id appears on
multiple days, use the date-qualified selector in the CLI.
## CLI access
Use the read-only CLI to find or print stored summaries:
```bash
openclaw meeting-notes list
openclaw meeting-notes show <session>
openclaw meeting-notes path <session>
openclaw meeting-notes path <session> --transcript
```
See [Meeting Notes CLI](/cli/meeting-notes) for the full command reference.
## Long meetings
For long meetings, utterances are appended to `transcript.jsonl` as they arrive.
Summary generation reads a bounded window controlled by
`plugins.entries.meeting-notes.config.maxUtterances` (default: `2000`) so a
multi-hour call does not require unbounded summary memory.
This means the transcript can keep growing on disk, while summarization stays
bounded. Increase `maxUtterances` when you need more of a multi-hour meeting in
the generated summary and speaker-labeled transcript section. Decrease it when
summaries are too slow or too large.
Current summaries are generated when a session stops, after an import, or when
the `summarize` action runs. They are not continuously rewritten for every
utterance.
## Troubleshooting
### `meeting_notes` is missing
Check that the plugin is installed or loaded from source, and that plugin
loading does not exclude it:
```bash
openclaw config validate
openclaw meeting-notes list
```
If `plugins.allow` is set, it must include `meeting-notes`. If `plugins.deny`
contains `meeting-notes`, remove it.
### Auto-start does not join Discord
Confirm the `autoStart` entry uses `providerId: "discord-voice"` and includes
both `guildId` and `channelId`. If you run multiple Discord accounts, include
`accountId`. Also verify Discord voice works outside Meeting Notes by joining
the same voice channel through the Discord voice commands.
### Summary is missing
Live sessions write `summary.md` when stopped. Stop the session with
`meeting_notes` action `stop`, then inspect it:
```bash
openclaw meeting-notes list
openclaw meeting-notes path <session>
```
Use `meeting_notes` action `summarize` to regenerate `summary.md` for an
existing stored session.
### Selector is ambiguous
If you reused a human session id such as `standup`, use the date-qualified
selector shown by `openclaw meeting-notes list`:
```bash
openclaw meeting-notes show 2026-05-22/standup
```
## Related
- [Meeting Notes CLI](/cli/meeting-notes)
- [Discord voice](/channels/discord#voice-mode)
- [Plugin management](/tools/plugin)
- [Plugin architecture](/plugins/architecture)

View File

@@ -151,7 +151,7 @@ commands.
| [diagnostics-otel](/plugins/reference/diagnostics-otel) | OpenClaw diagnostics OpenTelemetry exporter. | `@openclaw/diagnostics-otel`<br />npm; ClawHub: `clawhub:@openclaw/diagnostics-otel` | plugin |
| [diagnostics-prometheus](/plugins/reference/diagnostics-prometheus) | OpenClaw diagnostics Prometheus exporter. | `@openclaw/diagnostics-prometheus`<br />npm; ClawHub: `clawhub:@openclaw/diagnostics-prometheus` | plugin |
| [diffs](/plugins/reference/diffs) | Read-only diff viewer and file renderer for agents. | `@openclaw/diffs`<br />npm; ClawHub | contracts: tools; skills |
| [discord](/plugins/reference/discord) | Adds the Discord channel surface for sending and receiving OpenClaw messages. | `@openclaw/discord`<br />npm; ClawHub | channels: discord; contracts: meetingNotesSourceProviders |
| [discord](/plugins/reference/discord) | Adds the Discord channel surface for sending and receiving OpenClaw messages. | `@openclaw/discord`<br />npm; ClawHub | channels: discord; contracts: transcriptSourceProviders |
| [feishu](/plugins/reference/feishu) | Adds the Feishu channel surface for sending and receiving OpenClaw messages. | `@openclaw/feishu`<br />npm; ClawHub | channels: feishu; contracts: tools; skills |
| [google-meet](/plugins/reference/google-meet) | Join Google Meet calls through Chrome or Twilio transports. | `@openclaw/google-meet`<br />npm; ClawHub | contracts: tools |
| [googlechat](/plugins/reference/googlechat) | Adds the Google Chat channel surface for sending and receiving OpenClaw messages. | `@openclaw/googlechat`<br />npm; ClawHub | channels: googlechat |
@@ -175,9 +175,8 @@ commands.
## Source checkout only
| Plugin | Description | Distribution | Surface |
| ------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------- |
| [meeting-notes](/plugins/reference/meeting-notes) | Capture meeting transcripts from channel-owned sources and write summaries. | `@openclaw/meeting-notes`<br />source checkout only | contracts: meetingNotesSourceProviders, tools |
| [qa-channel](/plugins/reference/qa-channel) | Adds the QA Channel surface for sending and receiving OpenClaw messages. | `@openclaw/qa-channel`<br />source checkout only | channels: qa-channel |
| [qa-lab](/plugins/reference/qa-lab) | OpenClaw QA lab plugin with private debugger UI and scenario runner. | `@openclaw/qa-lab`<br />source checkout only | plugin |
| [qa-matrix](/plugins/reference/qa-matrix) | Matrix QA transport runner and substrate. | `@openclaw/qa-matrix`<br />source checkout only | plugin |
| Plugin | Description | Distribution | Surface |
| ------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------ | -------------------- |
| [qa-channel](/plugins/reference/qa-channel) | Adds the QA Channel surface for sending and receiving OpenClaw messages. | `@openclaw/qa-channel`<br />source checkout only | channels: qa-channel |
| [qa-lab](/plugins/reference/qa-lab) | OpenClaw QA lab plugin with private debugger UI and scenario runner. | `@openclaw/qa-lab`<br />source checkout only | plugin |
| [qa-matrix](/plugins/reference/qa-matrix) | Matrix QA transport runner and substrate. | `@openclaw/qa-matrix`<br />source checkout only | plugin |

View File

@@ -44,7 +44,7 @@ pnpm plugins:inventory:gen
| [diagnostics-otel](/plugins/reference/diagnostics-otel) | OpenClaw diagnostics OpenTelemetry exporter. | `@openclaw/diagnostics-otel`<br />npm; ClawHub: `clawhub:@openclaw/diagnostics-otel` | plugin |
| [diagnostics-prometheus](/plugins/reference/diagnostics-prometheus) | OpenClaw diagnostics Prometheus exporter. | `@openclaw/diagnostics-prometheus`<br />npm; ClawHub: `clawhub:@openclaw/diagnostics-prometheus` | plugin |
| [diffs](/plugins/reference/diffs) | Read-only diff viewer and file renderer for agents. | `@openclaw/diffs`<br />npm; ClawHub | contracts: tools; skills |
| [discord](/plugins/reference/discord) | Adds the Discord channel surface for sending and receiving OpenClaw messages. | `@openclaw/discord`<br />npm; ClawHub | channels: discord; contracts: meetingNotesSourceProviders |
| [discord](/plugins/reference/discord) | Adds the Discord channel surface for sending and receiving OpenClaw messages. | `@openclaw/discord`<br />npm; ClawHub | channels: discord; contracts: transcriptSourceProviders |
| [document-extract](/plugins/reference/document-extract) | Extract text and fallback page images from local document attachments. | `@openclaw/document-extract-plugin`<br />included in OpenClaw | contracts: documentExtractors |
| [duckduckgo](/plugins/reference/duckduckgo) | Adds web search provider support. | `@openclaw/duckduckgo-plugin`<br />included in OpenClaw | contracts: webSearchProviders |
| [elevenlabs](/plugins/reference/elevenlabs) | Adds media understanding provider support. Adds realtime transcription provider support. Adds text-to-speech provider support. | `@openclaw/elevenlabs-speech`<br />included in OpenClaw | contracts: mediaUnderstandingProviders, realtimeTranscriptionProviders, speechProviders |
@@ -73,7 +73,6 @@ pnpm plugins:inventory:gen
| [lobster](/plugins/reference/lobster) | Typed workflow tool with resumable approvals. | `@openclaw/lobster`<br />npm; ClawHub | contracts: tools |
| [matrix](/plugins/reference/matrix) | Adds the Matrix channel surface for sending and receiving OpenClaw messages. | `@openclaw/matrix`<br />ClawHub: `clawhub:@openclaw/matrix`; npm | channels: matrix |
| [mattermost](/plugins/reference/mattermost) | Adds the Mattermost channel surface for sending and receiving OpenClaw messages. | `@openclaw/mattermost`<br />included in OpenClaw | channels: mattermost |
| [meeting-notes](/plugins/reference/meeting-notes) | Capture meeting transcripts from channel-owned sources and write summaries. | `@openclaw/meeting-notes`<br />source checkout only | contracts: meetingNotesSourceProviders, tools |
| [memory-core](/plugins/reference/memory-core) | Adds memory embedding provider support. Adds agent-callable tools. | `@openclaw/memory-core`<br />included in OpenClaw | contracts: memoryEmbeddingProviders, tools |
| [memory-lancedb](/plugins/reference/memory-lancedb) | Adds agent-callable tools. | `@openclaw/memory-lancedb`<br />npm; ClawHub | contracts: tools |
| [memory-wiki](/plugins/reference/memory-wiki) | Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw. | `@openclaw/memory-wiki`<br />included in OpenClaw | contracts: tools; skills |

View File

@@ -16,7 +16,7 @@ Adds the Discord channel surface for sending and receiving OpenClaw messages.
## Surface
channels: discord; contracts: meetingNotesSourceProviders
channels: discord; contracts: transcriptSourceProviders
## Related docs

View File

@@ -1,23 +0,0 @@
---
summary: "Capture meeting transcripts from channel-owned sources and write summaries."
read_when:
- You are installing, configuring, or auditing the meeting-notes plugin
title: "Meeting Notes plugin"
---
# Meeting Notes plugin
Capture meeting transcripts from channel-owned sources and write summaries.
## Distribution
- Package: `@openclaw/meeting-notes`
- Install route: source checkout only
## Surface
contracts: meetingNotesSourceProviders, tools
## Related docs
- [meeting-notes](/plugins/meeting-notes)

View File

@@ -322,9 +322,7 @@ focused channel/runtime subpaths, `config-contracts`, `string-coerce-runtime`,
| `plugin-sdk/media-mime` | Narrow MIME normalization, file-extension mapping, MIME detection, and media-kind helpers |
| `plugin-sdk/media-store` | Narrow media store helpers such as `saveMediaBuffer` and `saveMediaStream` |
| `plugin-sdk/media-generation-runtime` | Shared media-generation failover helpers, candidate selection, and missing-model messaging |
| `plugin-sdk/meeting-notes` | Meeting notes source provider types, registry lookup, and provider id normalization helpers |
| `plugin-sdk/media-understanding` | Media understanding provider types plus provider-facing image/audio/structured-extraction helper exports |
| `plugin-sdk/meeting-notes` | Meeting notes source provider types, registry helpers, and provider id normalization |
| `plugin-sdk/text-chunking` | Text and markdown chunking/render helpers, markdown table conversion, directive-tag stripping, and safe-text utilities |
| `plugin-sdk/text-chunking` | Outbound text chunking helper |
| `plugin-sdk/speech` | Speech provider types plus provider-facing directive, registry, validation, OpenAI-compatible TTS builder, and speech helper exports |
@@ -338,7 +336,7 @@ focused channel/runtime subpaths, `config-contracts`, `string-coerce-runtime`,
| `plugin-sdk/music-generation-core` | Shared music-generation types, failover helpers, provider lookup, and model-ref parsing |
| `plugin-sdk/video-generation` | Video generation provider/request/result types |
| `plugin-sdk/video-generation-core` | Shared video-generation types, failover helpers, provider lookup, and model-ref parsing |
| `plugin-sdk/meeting-notes` | Shared meeting-notes source provider types, registry helpers, session descriptors, and utterance metadata |
| `plugin-sdk/transcripts` | Shared transcripts source provider types, registry helpers, session descriptors, and utterance metadata |
| `plugin-sdk/webhook-targets` | Webhook target registry and route-install helpers |
| `plugin-sdk/webhook-path` | Deprecated compatibility alias; use `plugin-sdk/webhook-ingress` |
| `plugin-sdk/web-media` | Shared remote/local media loading helpers |