Skip to content

fix(gateway): agent-scoped session keys on the wire; end the turn on a rejected chat.send - #525

Merged
MCERQUA merged 3 commits into
mainfrom
fix/gateway-agent-scoped-session-keys
Oct 4, 2026
Merged

MCERQUA merged 3 commits into
mainfrom
fix/gateway-agent-scoped-session-keys

Conversation

@MCERQUA

@MCERQUA MCERQUA commented Oct 4, 2026

Copy link
Copy Markdown
Owner

OpenClaw 2026.8.35 rejects a bare sessionKey such as main when more than one agent is configured ("Multiple agents are configured, but session key "main" has no explicit owner"). Every JamBot tenant has two agents, so voice would go silent on 8.35. OVU also treated that rejection as an ACK and heartbeated for 300 s before ending the turn with no error.

What changes

  • The connect hello already announces snapshot.sessionDefaults.defaultAgentId (present in 2026.5.7 and 2026.8.35). OVU stores it on every successful handshake.
  • wire_session_key() sends agent:<defaultAgentId>:<alias> for a bare key, on the wire only. Keys that are already agent-scoped, the unscoped global / unknown keys, and every key on a gateway that announces no default are sent unchanged. 2026.5.7 canonicalizes a bare main to that same prefixed key, so it is the same session on both versions.
  • Applied at all 8 outbound chat.send / chat.abort sites, plus the admin-install send. Internal keys (subscriptions, steer maps, caches, get_voice_session_key()) keep the short alias; inbound matching already accepts canonical event keys.
  • A res with ok: false / error for a chat.send now ends the turn with the existing failed-turn event (text_done, response: None, error). The dispatcher no longer marks a rejected send QUEUED, so it cannot claim another turn's follow-up run.
  • The fast lane's agent_id is a connection selector and still runs on the default agent; routing it to openvoiceui-fast is left as a separate decision.

Tests: 18 new in tests/test_gateway_session_keys.py; gateway modules 49 -> 67 passed. The full suite has the same 70 pre-existing failures before and after (401s in route tests in a bare env). Reverting the fixes turns 7 of the new tests red.

Rollout: rides the next fleet roll. Gate on test-dev (5.7) first: the log shows Gateway default agent: openvoiceui, the same conversation history continues across the change, and a forced rejection reaches the client within seconds. Plan: docs/jambot/openclaw-upgrade-2026.8.35.md §13 WO-1 (MIKE-AI repo).

Mike and others added 3 commits October 4, 2026 15:23
…ted chat.send

openclaw 2026.8.35 rejects a bare sessionKey in chat.send once more than one
agent is configured ("Multiple agents are configured, but session key "main"
has no explicit owner. Use an agent-prefixed session key"). Every JamBot
tenant sends GATEWAY_SESSION_KEY=main and has two agents (openvoiceui,
openvoiceui-fast), so voice would go silent on 8.35.

- Capture snapshot.sessionDefaults.defaultAgentId from the connect hello
  (res.payload; present in both 2026.5.7 and 2026.8.35) on every successful
  handshake, so reconnects refresh it.
- wire_session_key(): bare alias -> agent:<defaultAgentId>:<alias> on the wire.
  Unchanged when the key is already agent-scoped, is "global"/"unknown" (both
  versions keep those unscoped), or the gateway announced no default.
  2026.5.7 canonicalizes "main" to agent:<default>:main itself, so this is the
  same session on the current fleet.
- Applied to every outbound sessionKey: chat.send (main, empty-final retry,
  both subagent continuations, orphan continuation, steer), chat.abort, and
  the admin install chat.send. Subscriptions, steer maps, caches and
  get_voice_session_key() keep the short alias; _sk_match already matches
  canonical event keys against it.
- The fast lane's agent_id stays a connection selector (it never reached the
  gateway); not changed here.

A chat.send `res` with ok:false / error was treated as an ACK (and marked
QUEUED by the dispatcher), so the turn heartbeated to the 300s inner timeout
and ended as a null text_done with the reason lost. It is now terminal: the
stream emits the existing failed-turn event (text_done, response None, error)
immediately, and the dispatcher no longer marks a rejected send QUEUED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MCERQUA
MCERQUA enabled auto-merge (squash) October 4, 2026 16:08
@MCERQUA
MCERQUA merged commit 21a53c0 into main Oct 4, 2026
2 checks passed
@MCERQUA
MCERQUA deleted the fix/gateway-agent-scoped-session-keys branch October 4, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant