Summary
Voice message transcription (STT) stopped working after upgrading from v2026.4.2 → v2026.4.5. Telegram voice messages are no longer transcribed by the configured audio provider; the model receives the raw audio file instead.
Environment
- OpenClaw version: v2026.4.5
- Channel: Telegram (DM)
- STT provider: OpenAI-compatible endpoint (Parakeet / NVIDIA NeMo at a local URL)
- Config:
tools.media.audio.models[0].provider = "openai", tools.media.audio.models[0].baseUrl = <local Parakeet URL>
Behavior
v2026.4.2: Voice messages were transcribed correctly; echoTranscript fired (🎤 echo sent to user before agent reply).
v2026.4.5: No echo sent; model receives raw audio file; agent responds generically instead of to the voice content.
Root Cause (traced through compiled source)
In v2026.4.5, Telegram voice handling routes through applyMediaUnderstanding (apply-CU6lCv5P.js), which builds a media understanding provider registry via buildMediaUnderstandingRegistry (provider-registry-Qp9sisqM.js).
The openaiMediaUnderstandingProvider (in media-understanding-provider-BUTtadCJ.js) provides transcribeAudio and is the correct handler for provider: "openai" audio entries. However, it only gets registered if the "openai" bundled plugin is active.
The activation check in manifest-registry-Cqdpf6fh.js (resolvePluginActivationState) contains:
if (params.config.allow.length > 0 && !explicitlyAllowed) return {
enabled: false,
reason: "not in allowlist"
};
If a user has a non-empty plugins.allow list that doesn't include "openai", the openai bundled plugin is blocked — even though it's enabledByDefault: true and the user has a valid tools.media.audio config using the openai-compatible API.
The compat fallback in capability-provider-runtime-CMlMeixn.js (resolvePluginCapabilityProviders → withBundledPluginEnablementCompat) is supposed to handle this, but it only adds to plugins.entries (not plugins.allow), so the allowlist check still blocks activation.
The result: getMediaUnderstandingProvider("openai", providerRegistry) returns undefined, causing runProviderEntry to throw "Media provider not available: openai" (silently caught in runAttachmentEntries). No audio.transcription outputs are produced, echoTranscript never fires, and the raw audio file is passed to the model.
Workaround
Add "openai" to plugins.allow in openclaw.json:
"plugins": {
"allow": ["...", "openai"]
}
This allows the openai bundled plugin to load, which registers openaiMediaUnderstandingProvider with transcribeAudio. The configured tools.media.audio.models[0].baseUrl correctly overrides the default api.openai.com URL, so a local OpenAI-compatible endpoint (e.g. Parakeet) works as expected.
Also required: a models.providers.openai entry with apiKey so resolveUsableCustomProviderApiKey can return a key for requireApiKey:
"models": {
"providers": {
"openai": {
"apiKey": "local",
"baseUrl": "<your local STT endpoint>/v1",
"models": []
}
}
}
Expected Behavior
Users with a configured tools.media.audio using provider: "openai" should not need to manually add "openai" to plugins.allow. The audio pipeline should work regardless of whether the openai provider plugin is explicitly allowed, since the user has an explicit audio model config that references it.
The withBundledPluginEnablementCompat compat path should either also add the plugin to plugins.allow, or the allowlist check should be skipped for bundled plugins that are required by an explicit capability config entry.
Summary
Voice message transcription (STT) stopped working after upgrading from v2026.4.2 → v2026.4.5. Telegram voice messages are no longer transcribed by the configured audio provider; the model receives the raw audio file instead.
Environment
tools.media.audio.models[0].provider = "openai",tools.media.audio.models[0].baseUrl = <local Parakeet URL>Behavior
v2026.4.2: Voice messages were transcribed correctly;
echoTranscriptfired (🎤 echo sent to user before agent reply).v2026.4.5: No echo sent; model receives raw audio file; agent responds generically instead of to the voice content.
Root Cause (traced through compiled source)
In v2026.4.5, Telegram voice handling routes through
applyMediaUnderstanding(apply-CU6lCv5P.js), which builds a media understanding provider registry viabuildMediaUnderstandingRegistry(provider-registry-Qp9sisqM.js).The
openaiMediaUnderstandingProvider(inmedia-understanding-provider-BUTtadCJ.js) providestranscribeAudioand is the correct handler forprovider: "openai"audio entries. However, it only gets registered if the "openai" bundled plugin is active.The activation check in
manifest-registry-Cqdpf6fh.js(resolvePluginActivationState) contains:If a user has a non-empty
plugins.allowlist that doesn't include"openai", the openai bundled plugin is blocked — even though it'senabledByDefault: trueand the user has a validtools.media.audioconfig using the openai-compatible API.The compat fallback in
capability-provider-runtime-CMlMeixn.js(resolvePluginCapabilityProviders→withBundledPluginEnablementCompat) is supposed to handle this, but it only adds toplugins.entries(notplugins.allow), so the allowlist check still blocks activation.The result:
getMediaUnderstandingProvider("openai", providerRegistry)returnsundefined, causingrunProviderEntryto throw "Media provider not available: openai" (silently caught inrunAttachmentEntries). Noaudio.transcriptionoutputs are produced,echoTranscriptnever fires, and the raw audio file is passed to the model.Workaround
Add
"openai"toplugins.allowinopenclaw.json:This allows the openai bundled plugin to load, which registers
openaiMediaUnderstandingProviderwithtranscribeAudio. The configuredtools.media.audio.models[0].baseUrlcorrectly overrides the defaultapi.openai.comURL, so a local OpenAI-compatible endpoint (e.g. Parakeet) works as expected.Also required: a
models.providers.openaientry withapiKeysoresolveUsableCustomProviderApiKeycan return a key forrequireApiKey:Expected Behavior
Users with a configured
tools.media.audiousingprovider: "openai"should not need to manually add"openai"toplugins.allow. The audio pipeline should work regardless of whether the openai provider plugin is explicitly allowed, since the user has an explicit audio model config that references it.The
withBundledPluginEnablementCompatcompat path should either also add the plugin toplugins.allow, or the allowlist check should be skipped for bundled plugins that are required by an explicit capability config entry.