openclaw - ✅(Solved) Fix [Bug]: voice-call per-phone sessions use raw voice:* keys that conflict with gateway session canonicalization on restart [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#80064Fetched 2026-05-11 03:19:13
View on GitHub
Comments
2
Participants
3
Timeline
29
Reactions
2
Timeline (top)
referenced ×20commented ×2mentioned ×2subscribed ×2

Error Message

The installed Voice Call session resolver produced raw session keys:

Root Cause

Voice Call sessionScope: "per-phone" can lose repeat-caller continuity across Gateway restarts because the voice-call plugin resolves callers to raw voice:* session keys while Gateway startup migration canonicalizes those keys into agent:<agentId>:voice:*.

Fix Action

Fix / Workaround

Local workaround

Patching the installed voice-call resolver to emit agent-scoped keys stopped the mismatch locally:

PR fix notes

PR #80069: fix(voice-call): emit canonical agent-scoped session keys for per-phone and per-call scopes (#80064)

Description (problem / solution / changelog)

Problem

fix(voice-call): emit canonical agent-scoped session keys for per-phone caller sessions

Real behavior proof

  • Behavior or issue addressed: resolveVoiceCallSessionKey was emitting raw voice:* keys (e.g. voice:15550001111). After a Gateway restart, the migration canonicalizes these to agent:<agentId>:voice:*, so the old key no longer matched and caller sessions lost their conversation history.
  • Real environment tested: Local checkout of openclaw main (2026.5.10), Node 22, pnpm vitest run extensions/voice-call/src/config.test.ts.
  • Exact steps or command run after this patch:
    pnpm vitest run extensions/voice-call/src/config.test.ts
  • Evidence after fix:

$ pnpm vitest run extensions/voice-call/src/config.test.ts ✓ extensions/voice-call/src/config.test.ts (26 tests)

Test Files 1 passed (1) Tests 26 passed (26)

New test "uses configured agentId in per-phone session key" asserts key format `agent:myAgent:voice:15550001111`. Updated two existing tests to reflect new canonical format.
- **Observed result after fix:** 26/26 tests pass. Session keys now emit `agent:<agentId>:voice:<phone>`, matching the migration canonicalization. Cross-restart session continuity is preserved.
- **What was not tested:** End-to-end voice call across a live Gateway restart — this is unit-tested against `resolveVoiceCallSessionKey` directly.

## Changed files

- `extensions/voice-call/src/config.test.ts` (modified, +18/-2)
- `extensions/voice-call/src/config.ts` (modified, +6/-3)

Code Example

if (params.config.sessionScope === "per-call") return `voice:call:${params.callId}`;
const normalizedPhone = params.phone?.replace(/\D/g, "");
return normalizedPhone ? `voice:${normalizedPhone}` : `voice:${params.callId}`;

---

gateway: canonicalized orphaned session keys
Canonicalized 1 orphaned session key(s) in .../agents/main/sessions/sessions.json
Canonicalized 2 orphaned session key(s) in .../agents/main/sessions/sessions.json

---

agent:main:voice:<normalizedPhone>

---

voice:<normalizedPhone>

---

agent:<agentId>:voice:<normalizedPhone>
agent:<agentId>:voice:call:<callId>

---

function resolveVoiceCallSessionKey(params) {
   const explicit = params.explicitSessionKey?.trim();
   if (explicit) return explicit;
-  if (params.config.sessionScope === "per-call") return `voice:call:${params.callId}`;
+  const agentId = params.config.agentId?.trim() || "main";
+  const voicePrefix = `agent:${agentId}:voice`;
+  if (params.config.sessionScope === "per-call") return `${voicePrefix}:call:${params.callId}`;
   const normalizedPhone = params.phone?.replace(/\D/g, "");
-  return normalizedPhone ? `voice:${normalizedPhone}` : `voice:${params.callId}`;
+  return normalizedPhone ? `${voicePrefix}:${normalizedPhone}` : `${voicePrefix}:${params.callId}`;
 }
RAW_BUFFERClick to expand / collapse

What happened?

Voice Call sessionScope: "per-phone" can lose repeat-caller continuity across Gateway restarts because the voice-call plugin resolves callers to raw voice:* session keys while Gateway startup migration canonicalizes those keys into agent:<agentId>:voice:*.

This is a Voice Call regression/conflict after the per-phone/per-call sessionScope work in https://github.com/openclaw/openclaw/issues/45280

It is tangentially related to #63005, but this issue is narrower: the official @openclaw/voice-call plugin should use the post-migration/canonical session key format, or otherwise coordinate with the migration layer, so per-phone mode keeps its documented memory behavior.

Environment

  • OpenClaw 2026.5.7 (eeef486)
  • @openclaw/voice-call 2026.5.7
  • Ubuntu host, global npm install, Gateway service
  • Voice Call configured with:
    • agentId: "main"
    • sessionScope: "per-phone"

Observed behavior

The installed Voice Call session resolver produced raw session keys:

if (params.config.sessionScope === "per-call") return `voice:call:${params.callId}`;
const normalizedPhone = params.phone?.replace(/\D/g, "");
return normalizedPhone ? `voice:${normalizedPhone}` : `voice:${params.callId}`;

Gateway startup then repeatedly logged canonicalization of those raw keys:

gateway: canonicalized orphaned session keys
Canonicalized 1 orphaned session key(s) in .../agents/main/sessions/sessions.json
Canonicalized 2 orphaned session key(s) in .../agents/main/sessions/sessions.json

After startup migration, the session store contains canonical keys like:

agent:main:voice:<normalizedPhone>

but Voice Call inbound resolution still asks for:

voice:<normalizedPhone>

Expected behavior

sessionScope: "per-phone" should keep a stable session for the same caller across Gateway restarts.

Voice Call should resolve per-phone and per-call sessions using the same canonical session key format that survives Gateway migration, for example:

agent:<agentId>:voice:<normalizedPhone>
agent:<agentId>:voice:call:<callId>

Local workaround

Patching the installed voice-call resolver to emit agent-scoped keys stopped the mismatch locally:

 function resolveVoiceCallSessionKey(params) {
   const explicit = params.explicitSessionKey?.trim();
   if (explicit) return explicit;
-  if (params.config.sessionScope === "per-call") return `voice:call:${params.callId}`;
+  const agentId = params.config.agentId?.trim() || "main";
+  const voicePrefix = `agent:${agentId}:voice`;
+  if (params.config.sessionScope === "per-call") return `${voicePrefix}:call:${params.callId}`;
   const normalizedPhone = params.phone?.replace(/\D/g, "");
-  return normalizedPhone ? `voice:${normalizedPhone}` : `voice:${params.callId}`;
+  return normalizedPhone ? `${voicePrefix}:${normalizedPhone}` : `${voicePrefix}:${params.callId}`;
 }

Impact

  • Breaks or risks breaking the per-phone memory guarantee introduced by #45280.
  • Shows up after Gateway restarts, because startup migration rewrites/prunes raw session keys.
  • Can split the same caller between voice:* and agent:<agentId>:voice:* records.
  • Severity is high for phone assistants that rely on caller continuity.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

sessionScope: "per-phone" should keep a stable session for the same caller across Gateway restarts.

Voice Call should resolve per-phone and per-call sessions using the same canonical session key format that survives Gateway migration, for example:

agent:<agentId>:voice:<normalizedPhone>
agent:<agentId>:voice:call:<callId>

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING