When a user places a voice call from an instance chat page (AgentInstanceChatPage),
the call is now routed through the OpenClaw bridge instead of iAgent's
VoiceSessionManager SDK loop. iAgent voice behavior is completely unchanged.
Changes:
- Flutter: ChatPage accepts agentInstanceId, passes to AgentCallPage
- Flutter: AgentCallPage sends instance_id in livekit/token request body
- Flutter: AgentInstanceChatPage passes instance.id as agentInstanceId
- voice-service: livekit_token.py includes instance_id in dispatch metadata
- voice-agent: agent.py reads instance_id from metadata, passes to LLM
- voice-agent: agent_llm.py stores _instance_id, sends instanceId in voice/start
- agent-service voice/start: stores instanceId in session metadata; skips
VoiceSessionManager for instance mode (iAgent path unchanged)
- agent-service voice/inject: detects instanceId in session metadata and
fire-and-forgets to OpenClaw bridge; callback via openclaw-app-callback
emits text WS events that voice-agent collects for TTS playback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>