Filed against @openclaw/[email protected] (also present in 2026.6.5).
Summary
The voice_call tool's get_status action (and the legacy mode: "status" path) only checks the in-memory call manager via rt.manager.getCall(callId) || rt.manager.getCallByProviderCallId(callId). There is no fallback to the persisted call store when the in-memory record has been evicted.
This causes get_status to report { found: false } for calls that completed successfully and have a full transcript persisted to disk — the agent has no way to retrieve the conversation that happened.
Root cause
In dist/index.js:
case "get_status": {
const callId = normalizeOptionalString(rawParams.callId) ?? "";
const call = rt.manager.getCall(callId) || rt.manager.getCallByProviderCallId(callId);
return json(call ? { found: true, call } : { found: false });
}
rt.manager.getCall() is an in-memory lookup. Once a call exits the manager's active map (cleanup after completion, gateway restart, or simply enough time passing), this returns undefined regardless of whether a persisted record exists.
Meanwhile, the full call record — including a complete turn-by-turn transcript — is independently persisted under plugin_state_entries (plugin_id=voice-call) as base64-encoded, chunked JSON blobs keyed like event:<seq6>:<sequence>:<uuid>:chunk:NNNN. This data is confirmed present and complete (verified manually via direct SQLite query) for calls where get_status reports found: false.
Repro
- Initiate an outbound call via
voice_call (initiate_call).
- Let the call complete naturally.
- Wait — even a few minutes is enough, and a gateway restart in between guarantees it — then call
get_status with the same callId.
- Observe:
{ found: false }, despite the call having completed normally and a full transcript existing in the plugin's persisted SQLite state.
Impact
Any agent workflow that says "call me and report back what I said" silently fails at the reporting step. The agent has no way to know the call succeeded or to retrieve what was said — it can only report that the call status is unknown, which reads to the end user as if voice memory/transcription doesn't work at all, when in fact the data is sitting right there in the plugin's own store.
Suggested fix
get_status (and mode: "status") should fall back to querying the persisted call store (the same one transcripts are written to) when the in-memory manager lookup misses, before returning found: false. Alternatively, expose a dedicated get_transcript action that reads directly from the persisted store by callId, independent of in-memory manager state, since transcripts are clearly intended to survive past the live call lifecycle (they're written incrementally during the call as discrete event chunks).
Happy to provide the decoded persisted record structure if useful for reproducing.
Filed against
@openclaw/[email protected](also present in2026.6.5).Summary
The
voice_calltool'sget_statusaction (and the legacymode: "status"path) only checks the in-memory call manager viart.manager.getCall(callId) || rt.manager.getCallByProviderCallId(callId). There is no fallback to the persisted call store when the in-memory record has been evicted.This causes
get_statusto report{ found: false }for calls that completed successfully and have a full transcript persisted to disk — the agent has no way to retrieve the conversation that happened.Root cause
In
dist/index.js:rt.manager.getCall()is an in-memory lookup. Once a call exits the manager's active map (cleanup after completion, gateway restart, or simply enough time passing), this returnsundefinedregardless of whether a persisted record exists.Meanwhile, the full call record — including a complete turn-by-turn transcript — is independently persisted under
plugin_state_entries(plugin_id=voice-call) as base64-encoded, chunked JSON blobs keyed likeevent:<seq6>:<sequence>:<uuid>:chunk:NNNN. This data is confirmed present and complete (verified manually via direct SQLite query) for calls whereget_statusreportsfound: false.Repro
voice_call(initiate_call).get_statuswith the samecallId.{ found: false }, despite the call having completed normally and a full transcript existing in the plugin's persisted SQLite state.Impact
Any agent workflow that says "call me and report back what I said" silently fails at the reporting step. The agent has no way to know the call succeeded or to retrieve what was said — it can only report that the call status is unknown, which reads to the end user as if voice memory/transcription doesn't work at all, when in fact the data is sitting right there in the plugin's own store.
Suggested fix
get_status(andmode: "status") should fall back to querying the persisted call store (the same one transcripts are written to) when the in-memory manager lookup misses, before returningfound: false. Alternatively, expose a dedicatedget_transcriptaction that reads directly from the persisted store bycallId, independent of in-memory manager state, since transcripts are clearly intended to survive past the live call lifecycle (they're written incrementally during the call as discrete event chunks).Happy to provide the decoded persisted record structure if useful for reproducing.