diff --git a/app/src/components/skills/MeetingBotsCard.tsx b/app/src/components/skills/MeetingBotsCard.tsx
index b357f0103..6d0d3fa47 100644
--- a/app/src/components/skills/MeetingBotsCard.tsx
+++ b/app/src/components/skills/MeetingBotsCard.tsx
@@ -202,7 +202,15 @@ function MeetingBotsInline({ onToast, hasSubmittedRef }: MeetingBotsInlineProps)
const { t } = useT();
const dispatch = useAppDispatch();
const [meetUrl, setMeetUrl] = useState('');
- const [respondTo] = useState('');
+ // The participant the bot answers to (authorized speaker). Wired to the
+ // backend join payload as `respondToParticipant` → `respondTo`, which the
+ // meeting stream uses to gate in-call requests to this speaker only.
+ const [respondTo, setRespondTo] = useState('');
+ // Active (respond when addressed) vs listen-only (transcribe only). Defaults
+ // to active; the bot still only replies after being addressed by the wake
+ // phrase. Forwarded to the backend as `listenOnly` and mirrored into the
+ // meet slice so the active view shows the right status.
+ const [listenOnly, setListenOnly] = useState(false);
const personaDisplayName = useAppSelector(selectPersonaDisplayName);
const personaDescription = useAppSelector(selectPersonaDescription);
const selectedMascotId = useAppSelector(selectSelectedMascotId);
@@ -234,7 +242,7 @@ function MeetingBotsInline({ onToast, hasSubmittedRef }: MeetingBotsInlineProps)
}, [refreshRecentCalls]);
const selectedLabel = t('skills.meetingBots.platforms.gmeet');
- const agentName = personaDisplayName.trim() || 'OpenHuman';
+ const agentName = personaDisplayName.trim() || 'Tiny';
const systemPrompt = personaDescription.trim() || undefined;
const mascotId = selectedMascotId ?? (mascotColor === 'custom' ? undefined : mascotColor);
const riveColors =
@@ -264,7 +272,7 @@ function MeetingBotsInline({ onToast, hasSubmittedRef }: MeetingBotsInlineProps)
hasSubmittedRef.current = true;
try {
const meetingId = crypto.randomUUID();
- dispatch(setBackendMeetJoining({ meetUrl: meetUrl.trim(), meetingId }));
+ dispatch(setBackendMeetJoining({ meetUrl: meetUrl.trim(), meetingId, listenOnly }));
await joinMeetViaBackendBot({
meetUrl,
displayName: agentName,
@@ -275,6 +283,7 @@ function MeetingBotsInline({ onToast, hasSubmittedRef }: MeetingBotsInlineProps)
riveColors,
correlationId: meetingId,
respondToParticipant: respondTo.trim() || undefined,
+ listenOnly,
});
} catch (err) {
const message = err instanceof Error ? err.message : t('skills.meetingBots.failedToStart');
@@ -315,6 +324,44 @@ function MeetingBotsInline({ onToast, hasSubmittedRef }: MeetingBotsInlineProps)
/>
+
+
+
+
{error && (