-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
[Bug]: google_meet & voice_call route every call to single configured agent in multi-agent deployments #77753
Copy link
Copy link
Closed
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.Channel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Description
Metadata
Metadata
Assignees
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.Channel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Type
Fields
Priority
None yet
Summary
In multi-agent OpenClaw deployments (per-user agents on Slack/Telegram/Discord), when any agent invokes the
google_meettool (action=join,create+joinAfterCreate,test_speech) or thevoice_calltool (initiate_call), the outbound voice call is always routed to the single configured agent (voiceConfig.agentId ?? "main") instead of the agent that actually initiated the call. Every user hears the samemainagent voice.Reproduction
slack-u123,slack-u456).slack-u123) asks the bot to join a Google Meet.slack-u456) asks the bot to join a different Google Meet concurrently.main), not the per-user agent.Root Causes (multiple, must all be addressed)
extensions/google-meet/index.ts:993andextensions/voice-call/index.ts:609register tools viaapi.registerTool({...})static-object form. The factory formapi.registerTool((ctx) => ({...}), { name })is required to capturectx.agentId.callGoogleMeetGatewayFromTool(google-meet/index.ts:449-470) hops viacallGatewayFromCli(CLI bridge → WebSocket →gateway-rpc.runtime.js). Tool-side closures cannot reach the gateway handler.agentIdmust travel as a serialized RPC field.agentId—googlemeet.join(line 705-720),googlemeet.create,googlemeet.test_speechbuildrt.join(request)withoutagentId.JoinMeetRequest/rt.joinshape lacksagentId—extensions/google-meet/src/runtime.ts:351; same forjoinMeetViaVoiceCallGatewayatruntime.ts:443-468.voicecall.startRPC handler doesn't acceptagentId—extensions/voice-call/index.ts:581-606reads onlyto/message/dtmfSequence/mode.initiateCallAndRespond(line 335-353) callsmanager.initiateCall(to, undefined, {...})with noagentIdslot.effectiveConfig.agentId, notcall.agentId:voice-call/src/webhook.ts:884+response-generator.ts:214(voiceConfig.agentId ?? "main").voice-call/src/runtime.ts:348(effectiveConfig.agentId ?? "main").voice-call/src/runtime.ts:377(same fallback).voice_calltool itself has the same defect —extensions/voice-call/index.ts:635initiate_callaction callsrt.manager.initiateCall(to, undefined, {...})with noagentId.Impact
mainagent voicemainagent voicemode=realtime)effectiveConfig.agentIdcall.agentIdvoiceConfig.agentIdcall.agentIdmainProposed Fix (high-level)
Design invariant: resolve effective
agentIdexactly once at call creation, persist it onCallRecord, and consumecall.agentIdat every downstream site through a centralized helper. No optional-fallback chain at every hop.google_meetandvoice_calltools to factory pattern with{ name }opts (required bysrc/plugins/registry.ts:506-509for factory-form name auto-derivation).ctx.agentIdinto the gateway-bound RPC payload at the dispatch boundary; thread it throughgooglemeet.{join,create,test_speech}handlers →JoinMeetRequest/Create/TestSpeech→rt.join→joinMeetViaVoiceCallGateway→voicecall.startRPC →manager.initiateCall→CallRecord.agentId.agentIdon inboundCallRecordatmanager/events.ts:createWebhookCall(DID-route default, frozen at creation to prevent hot-reload drift).extensions/voice-call/src/util/resolve-call-agent-id.tswith a single precedence helper:call.agentId || effectiveConfig.agentId || "main". Consume from webhook, both realtime consult lanes, and response-generator.agent:${agentId}:google-meet:${session.id}) to prevent collisions on shared Twilio dial-ins (pattern reused fromextensions/google-meet/src/agent-consult.ts:50-57).Scope
~14 files across two extensions plus one new helper module:
extensions/google-meet/:index.ts,src/runtime.ts,src/voice-call-gateway.tsextensions/voice-call/:index.ts,src/types.ts,src/manager/outbound.ts,src/manager/events.ts,src/webhook.ts,src/response-generator.ts,src/runtime.ts, newsrc/util/resolve-call-agent-id.tsPlus unit tests (per-file) and one integration test driving the webhook → response-generator boundary.
Backward Compatibility
CallRecordschema: new optional field, Zod strip-mode round-trip preserves old records.voicecall.startRPC: old handlers ignore unknownagentId/sessionKeyparams.ctx.agentId === "main"(or undefined → falls through helper to config default →"main"). Identical pre-PR behavior.Map+ per-podcalls.jsonl); during a rolling window, old-podvoicecall.startinvocations silently drop the field and fall back toeffectiveConfig.agentId. Uniform rollout recommended.Related
PR with full plan and detailed change set will follow shortly. Filed by quangtran88 from
oneclaw/oneclaw.improvementfor an OneClaw multi-agent deployment.