+ Use a key from an OpenAI project with GPT-Live enabled, separate from + any key used for task inference. It is used only by this + deployment's control plane to open voice calls; it is never sent + to agents or task sandboxes. If the deployment sets + R_VOICE_OPENAI_API_KEY, that key is used instead. +
+ {allowBlankApiKey ? ( ++ Leave blank to keep the existing API key. +
+ ) : null} + {fieldErrors.apiKey ? ( +{fieldErrors.apiKey[0]}
+ ) : null} +{formError}
+ ) : null} + > + ); +} + function ElevenLabsConnectionFields({ form, fieldErrors, @@ -1426,6 +1505,14 @@ export function Integrations() { const [granolaForm, setGranolaForm] = useState- Use a key from an OpenAI project with GPT-Live enabled, separate from - any key used for task inference. It is used only by this - deployment's control plane to open voice calls; it is never sent - to agents or task sandboxes. If the deployment sets - R_VOICE_OPENAI_API_KEY, that key is used instead. -
{allowBlankApiKey ? (
Leave blank to keep the existing API key.
@@ -3243,11 +3236,7 @@ export function Integrations() {
isPending={saveVoiceConnection.isPending}
isLoading={isVoiceConnected && voiceConnection.isPending}
description={
- <>
- Store an OpenAI API key with GPT-Live access for this deployment.
- The key stays encrypted server-side and is used only by the control
- plane to open voice calls on Sessions.
- >
+ <>Store an OpenAI API key with GPT-Live access for this deployment.>
}
onSubmit={handleVoiceSubmit}
>
From c14e03c196d968c374d99ab7330c437814bc0afc Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Thu, 10 Sep 2026 19:02:48 -0400
Subject: [PATCH 4/4] feat: show Voice as connected when the environment
provides the key
The voice connection query reports where the key comes from. With
R_VOICE_OPENAI_API_KEY set, the card sits under Connected with a note and no
configure or disconnect action, since there is nothing to manage in Settings.
---
.../components/settings/Integrations.test.tsx | 35 +++++++++++++++++++
.../src/components/settings/Integrations.tsx | 27 ++++++++++----
.../trpc/commands/mcp-connections/index.ts | 23 ++++++++++--
3 files changed, 76 insertions(+), 9 deletions(-)
diff --git a/apps/web/src/components/settings/Integrations.test.tsx b/apps/web/src/components/settings/Integrations.test.tsx
index cbd03d9f3a..ab634f5533 100644
--- a/apps/web/src/components/settings/Integrations.test.tsx
+++ b/apps/web/src/components/settings/Integrations.test.tsx
@@ -50,6 +50,7 @@ const state = vi.hoisted(() => ({
},
voiceConnection: null as null | {
authStatus?: string | null;
+ source?: 'environment' | 'connection';
},
grafanaConnection: null as null | {
authStatus?: string | null;
@@ -517,6 +518,7 @@ describe('Integrations settings', () => {
beforeEach(() => {
vi.clearAllMocks();
window.history.replaceState(null, '', '/settings/integrations');
+ state.voiceConnection = null;
state.deploymentEnablements = [];
state.integrationsEnabled = true;
state.oauthReadiness = [{ mcpId: 'linear', status: 'ready' }];
@@ -2217,4 +2219,37 @@ describe('Integrations settings', () => {
expect.anything(),
);
});
+
+ it('shows Voice as connected when the environment provides the key', async () => {
+ state.isAdmin = true;
+ state.deploymentEnablements = [];
+ state.userConnections = [];
+ state.voiceConnection = {
+ authStatus: 'authenticated',
+ source: 'environment',
+ };
+
+ render(