From 651166be365fc7dbee8b7c4b4d114018eaebb446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 22 Apr 2026 21:28:34 +0200 Subject: [PATCH] refactor(exa-app): drop EXA_API_KEY env var after flag-based install Removes the last coupling of Exa to deployment-time config after the infrastructure PR moved pre-installation to a registration flag: - Drops the `EXA_API_KEY` env var. Exa is now registered as an `ApplicationRegistration` and its API key lives on the registration's `ApplicationRegistrationVariable` row, same as any other app. - Updates the Exa app manifest + README to describe the admin flow (register app, flip `autoInstallOnNewWorkspaces`, set EXA_API_KEY server variable) instead of env-var seeding. - Updates the AI chat preload TODO comment to reflect the flag-based install model. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/twenty-apps/community/exa/README.md | 18 +++++++++--------- .../community/exa/src/application.config.ts | 2 +- .../twenty-config/config-variables.ts | 15 --------------- .../ai-chat/services/chat-execution.service.ts | 2 +- 4 files changed, 11 insertions(+), 26 deletions(-) diff --git a/packages/twenty-apps/community/exa/README.md b/packages/twenty-apps/community/exa/README.md index 6b309a57f68..31de302ce60 100644 --- a/packages/twenty-apps/community/exa/README.md +++ b/packages/twenty-apps/community/exa/README.md @@ -3,16 +3,16 @@ Exposes [Exa](https://exa.ai) structured web search to Twenty AI agents (chat + workflow agents + MCP) as the `app_exa_web_search` tool. -## Configuration +## Installation -Server admin sets two env vars: - -- `PRE_INSTALLED_APPS=@twenty-apps/exa` — installs this app on every new - workspace. Existing workspaces backfill via the - `install-pre-installed-apps` CLI command. -- `EXA_API_KEY=` — auto-seeded into the application registration's - server variables at server bootstrap. No per-workspace configuration - needed. +1. Register the app on the Twenty server once (admin API / UI): + `@twenty-apps/exa` from npm. +2. Set `autoInstallOnNewWorkspaces=true` on the registration so it's + installed on every new workspace. Existing workspaces can be + backfilled via the `install-pre-installed-apps` CLI command. +3. Set the `EXA_API_KEY` server variable on the registration to your Exa + API key. The value is injected into every logic function execution — + no per-workspace configuration needed. ## Billing diff --git a/packages/twenty-apps/community/exa/src/application.config.ts b/packages/twenty-apps/community/exa/src/application.config.ts index bc6690b204f..0eda8f707ee 100644 --- a/packages/twenty-apps/community/exa/src/application.config.ts +++ b/packages/twenty-apps/community/exa/src/application.config.ts @@ -12,7 +12,7 @@ export default defineApplication({ serverVariables: { EXA_API_KEY: { description: - 'Exa API key. Server admins can set this via the EXA_API_KEY env var, which is auto-seeded into this application registration at server bootstrap.', + 'Exa API key. Set by the server admin on this registration after installation; the value is injected into every logic function execution.', isSecret: true, isRequired: true, }, diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts index 09a68fda367..e313cfac950 100644 --- a/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts @@ -4,7 +4,6 @@ import { plainToClass } from 'class-transformer'; import { IsDefined, IsOptional, - IsString, IsUrl, ValidateIf, type ValidationError, @@ -13,7 +12,6 @@ import { import { isDefined } from 'twenty-shared/utils'; import { type LoggerOptions } from 'typeorm/logger/LoggerOptions'; -import { parsePreInstalledApps } from 'src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util'; import { LogicFunctionDriverType } from 'src/engine/core-modules/logic-function/logic-function-drivers/interfaces/logic-function-driver.interface'; import { type AwsRegion } from 'src/engine/core-modules/twenty-config/interfaces/aws-region.interface'; import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; @@ -676,19 +674,6 @@ export class ConfigVariables { @CastToPositiveNumber() CODE_INTERPRETER_TIMEOUT_MS = 300_000; - @ConfigVariablesMetadata({ - group: ConfigVariablesGroup.LLM, - description: - 'Exa API key. Seeded into the @twenty-apps/exa application registration as a server-level variable at bootstrap, so logic function handlers can read it from their execution env. Required only when the Exa app is listed in PRE_INSTALLED_APPS.', - type: ConfigVariableType.STRING, - isSensitive: true, - }) - @ValidateIf((env) => - parsePreInstalledApps(env.PRE_INSTALLED_APPS).includes('@twenty-apps/exa'), - ) - @IsString() - EXA_API_KEY?: string; - @ConfigVariablesMetadata({ group: ConfigVariablesGroup.ANALYTICS_CONFIG, description: 'Enable or disable analytics for telemetry', diff --git a/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts b/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts index dfe1c58c8f7..ec2e62191f6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts @@ -142,7 +142,7 @@ export class ChatExecutionService { // Preload the Exa app tool (shipped as `@twenty-apps/exa`) so chat has // structured web search ready without discovery. getToolsByName silently // skips the entry when the workspace doesn't have the Exa app installed - // (admin didn't add it to PRE_INSTALLED_APPS or backfill hasn't run). + // (admin hasn't registered it + flipped `autoInstallOnNewWorkspaces`). // TODO(app-preloading): move this list into the app manifest so any // app can declare `preloadedInChat: true` instead of hardcoding here. const toolNamesToPreload = [...COMMON_PRELOAD_TOOLS, 'app_exa_web_search'];