diff --git a/docs/plugins/google-meet.md b/docs/plugins/google-meet.md index 3a8b1720d6e..3bc41cbcd10 100644 --- a/docs/plugins/google-meet.md +++ b/docs/plugins/google-meet.md @@ -12,6 +12,9 @@ Google Meet participant support for OpenClaw — the plugin is explicit by desig - `realtime` voice is the default mode. - Realtime voice can call back into the full OpenClaw agent when deeper reasoning or tools are needed. +- Agents choose the join behavior with `mode`: use `realtime` for live + listen/talk-back, or `transcribe` to join/control the browser without the + realtime voice bridge. - Auth starts as personal Google OAuth or an already signed-in Chrome profile. - There is no automatic consent announcement. - The default Chrome audio backend is `BlackHole 2ch`. @@ -79,10 +82,16 @@ Or let an agent join through the `google_meet` tool: ```json { "action": "join", - "url": "https://meet.google.com/abc-defg-hij" + "url": "https://meet.google.com/abc-defg-hij", + "transport": "chrome-node", + "mode": "realtime" } ``` +For an observe-only/browser-control join, set `"mode": "transcribe"`. That does +not start the duplex realtime model bridge, so it will not talk back into the +meeting. + Chrome joins as the signed-in Chrome profile. In Meet, pick `BlackHole 2ch` for the microphone/speaker path used by OpenClaw. For clean duplex audio, use separate virtual devices or a Loopback-style graph; a single BlackHole device is diff --git a/extensions/google-meet/index.ts b/extensions/google-meet/index.ts index 9b5b13c147b..c9b64993728 100644 --- a/extensions/google-meet/index.ts +++ b/extensions/google-meet/index.ts @@ -35,7 +35,7 @@ const googleMeetConfigSchema = { }, defaultMode: { label: "Default Mode", - help: "Realtime voice is the default.", + help: "Realtime starts the duplex voice model loop. Transcribe joins/observes without the realtime talk-back bridge.", }, "chrome.audioBackend": { label: "Chrome Audio Backend", @@ -148,7 +148,13 @@ const GoogleMeetToolSchema = Type.Object({ transport: Type.Optional( Type.String({ enum: ["chrome", "chrome-node", "twilio"], description: "Join transport" }), ), - mode: Type.Optional(Type.String({ enum: ["realtime", "transcribe"], description: "Join mode" })), + mode: Type.Optional( + Type.String({ + enum: ["realtime", "transcribe"], + description: + "Join mode. realtime starts live listen/talk-back through the realtime voice model; transcribe joins without the realtime talk-back bridge.", + }), + ), dialInNumber: Type.Optional(Type.String({ description: "Meet dial-in number for Twilio" })), pin: Type.Optional(Type.String({ description: "Meet phone PIN for Twilio" })), dtmfSequence: Type.Optional(Type.String({ description: "Explicit DTMF sequence for Twilio" })), diff --git a/extensions/google-meet/src/cli.ts b/extensions/google-meet/src/cli.ts index 8001330b07e..8dff6026db7 100644 --- a/extensions/google-meet/src/cli.ts +++ b/extensions/google-meet/src/cli.ts @@ -177,7 +177,10 @@ export function registerGoogleMeetCli(params: { .command("join") .argument("[url]", "Explicit https://meet.google.com/... URL") .option("--transport ", "Transport: chrome, chrome-node, or twilio") - .option("--mode ", "Mode: realtime or transcribe") + .option( + "--mode ", + "Mode: realtime for live talk-back, transcribe to join without the realtime voice bridge", + ) .option("--message ", "Realtime speech to trigger after join") .option("--dial-in-number ", "Meet dial-in number for Twilio transport") .option("--pin ", "Meet phone PIN; # is appended if omitted") @@ -200,7 +203,10 @@ export function registerGoogleMeetCli(params: { .command("test-speech") .argument("[url]", "Explicit https://meet.google.com/... URL") .option("--transport ", "Transport: chrome, chrome-node, or twilio") - .option("--mode ", "Mode: realtime or transcribe") + .option( + "--mode ", + "Mode: realtime for live talk-back, transcribe to join without the realtime voice bridge", + ) .option( "--message ", "Realtime speech to trigger",