From 8a84e32cf60405bd0776f62b522674d240a17721 Mon Sep 17 00:00:00 2001
From: BugIsGod <87571967+bugisthegod@users.noreply.github.com>
Date: Wed, 8 Apr 2026 13:01:49 +0100
Subject: [PATCH] fix(ai): use @ai-sdk/openai-compatible for third-party
providers (#19438)
## Summary:
I found a bug: 404 call when I use third-party providers (I used
deepseek). I found the final request url is:
`https://api.deepseek.com/v1/responses' `if we use createOpenAI. But the
correct one should be `https://api.provider.com/v1/chat/completions` for
the thirty provider. So I replace createOpenAI with
createOpenAICompatible in the openai-compatible provider path.
**Reproduction**: Add DeepSeek as a new AI provider (deepseek-chat,
deepseek-reasoner)
Also check the source code in Open Code project, they also use
createOpenAICompatible for the @ai-sdk/openai-compatible scenario
official docs: https://ai-sdk.dev/providers/openai-compatible-providers
https://ai-sdk.dev/providers/ai-sdk-providers/openai
## Before
## After
## Backend error log
```json
[1] [Nest] 50907 - 07/04/2026, 23:48:57 LOG [ChatExecutionService] Starting chat execution with model deepseek/deepseek-chat, 4 active tools
[1] APICallError [AI_APICallError]: Not Found
[1] at /Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2512:14
[1] at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
[1] at async postToApi (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2373:28)
[1] at async OpenAIResponsesLanguageModel.doStream (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/openai/dist/index.js:4925:50)
[1] at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7106:27)
[1] at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24
[1] at async _retryWithExponentialBackoff (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2599:12)
[1] at async streamStep (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7063:17)
[1] at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7455:9)
[1] at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24 {
[1] cause: undefined,
[1] url: 'https://api.deepseek.com/v1/responses',
[1] requestBodyValues: {
[1] model: 'deepseek-chat',
[1] input: [ [Object], [Object] ],
[1] temperature: undefined,
[1] top_p: undefined,
[1] max_output_tokens: undefined,
[1] conversation: undefined,
[1] max_tool_calls: undefined,
[1] metadata: undefined,
[1] parallel_tool_calls: undefined,
[1] previous_response_id: undefined,
[1] store: undefined,
[1] user: undefined,
[1] instructions: undefined,
[1] service_tier: undefined,
[1] include: undefined,
[1] prompt_cache_key: undefined,
[1] prompt_cache_retention: undefined,
[1] safety_identifier: undefined,
[1] top_logprobs: undefined,
[1] truncation: undefined,
[1] tools: [ [Object], [Object], [Object], [Object] ],
[1] tool_choice: 'auto',
[1] stream: true
[1] },
[1] statusCode: 404,
[1] responseHeaders: {
[1] 'access-control-allow-credentials': 'true',
[1] connection: 'keep-alive',
[1] 'content-length': '0',
[1] date: 'Tue, 07 Apr 2026 22:48:57 GMT',
[1] server: 'elb',
[1] 'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
[1] vary: 'origin, access-control-request-method, access-control-request-headers',
[1] via: '1.1 83867089cd39052cd05f9e04909bedde.cloudfront.net (CloudFront)',
[1] 'x-amz-cf-id': 'O4b0VTi9Q1VVmTmq6czGlEWst7IPnAQl544hB7uIvfnSphBvUKbZTw==',
[1] 'x-amz-cf-pop': 'DUB56-P3',
[1] 'x-cache': 'Error from cloudfront',
[1] 'x-content-type-options': 'nosniff',
[1] 'x-ds-trace-id': 'a90e91809d285170338ef077f67ae2be'
[1] },
[1] responseBody: '',
[1] isRetryable: false,
[1] data: undefined,
[1] Symbol(vercel.ai.error): true,
[1] Symbol(vercel.ai.error.AI_APICallError): true
[1] }
[1] Exception Captured
[1] undefined
[1] [
[1] NoOutputGeneratedError [AI_NoOutputGeneratedError]: No output generated. Check the stream for errors.
[1] at Object.flush (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:6656:103)
[1] at invokePromiseCallback (node:internal/webstreams/util:172:10)
[1] at Object. (node:internal/webstreams/util:177:23)
[1] at transformStreamDefaultSinkCloseAlgorithm (node:internal/webstreams/transformstream:621:43)
[1] at node:internal/webstreams/transformstream:379:11
[1] at writableStreamDefaultControllerProcessClose (node:internal/webstreams/writablestream:1162:28)
[1] at writableStreamDefaultControllerAdvanceQueueIfNeeded (node:internal/webstreams/writablestream:1253:5)
[1] at writableStreamDefaultControllerClose (node:internal/webstreams/writablestream:1220:3)
[1] at writableStreamClose (node:internal/webstreams/writablestream:722:3)
[1] at writableStreamDefaultWriterClose (node:internal/webstreams/writablestream:1091:10) {
[1] cause: undefined,
[1] Symbol(vercel.ai.error): true,
[1] Symbol(vercel.ai.error.AI_NoOutputGeneratedError): true
[1] }
[1] ]
[1] [Nest] 50907 - 07/04/2026, 23:48:59 LOG [BullMQDriver] Job 24 with name StreamAgentChatJob processed on queue ai-stream-queue in 2756.63ms
---
packages/twenty-server/package.json | 1 +
.../services/sdk-provider-factory.service.ts | 12 ++++-----
yarn.lock | 26 +++++++++++++++++++
3 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/packages/twenty-server/package.json b/packages/twenty-server/package.json
index 17826ee1fe..d7c9daa9b3 100644
--- a/packages/twenty-server/package.json
+++ b/packages/twenty-server/package.json
@@ -20,6 +20,7 @@
"@ai-sdk/google": "^3.0.30",
"@ai-sdk/mistral": "^3.0.20",
"@ai-sdk/openai": "^3.0.30",
+ "@ai-sdk/openai-compatible": "^2.0.40",
"@ai-sdk/provider-utils": "^4.0.15",
"@ai-sdk/xai": "^3.0.57",
"@aws-sdk/client-lambda": "3.1001.0",
diff --git a/packages/twenty-server/src/engine/metadata-modules/ai/ai-models/services/sdk-provider-factory.service.ts b/packages/twenty-server/src/engine/metadata-modules/ai/ai-models/services/sdk-provider-factory.service.ts
index 0f2b979ab4..d3c1cda9b9 100644
--- a/packages/twenty-server/src/engine/metadata-modules/ai/ai-models/services/sdk-provider-factory.service.ts
+++ b/packages/twenty-server/src/engine/metadata-modules/ai/ai-models/services/sdk-provider-factory.service.ts
@@ -8,6 +8,7 @@ import { createAnthropic, type AnthropicProvider } from '@ai-sdk/anthropic';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createMistral } from '@ai-sdk/mistral';
import { createOpenAI, type OpenAIProvider } from '@ai-sdk/openai';
+import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { createXai } from '@ai-sdk/xai';
import { type LanguageModel } from 'ai';
import { type AiSdkPackage } from 'twenty-shared/ai';
@@ -80,11 +81,7 @@ export class SdkProviderFactoryService {
}
getRawOpenAIProvider(providerName: string): OpenAIProvider | undefined {
- return this.getRawProvider(
- providerName,
- AI_SDK_OPENAI,
- AI_SDK_OPENAI_COMPATIBLE,
- );
+ return this.getRawProvider(providerName, AI_SDK_OPENAI);
}
clearCache(): void {
@@ -158,9 +155,10 @@ export class SdkProviderFactoryService {
throw new Error('baseUrl is required for openai-compatible providers');
}
- const provider = createOpenAI({
+ const provider = createOpenAICompatible({
+ name: config.name ?? 'openai-compatible',
baseURL: config.baseUrl,
- apiKey: config.apiKey ?? '',
+ ...(config.apiKey && { apiKey: config.apiKey }),
});
return {
diff --git a/yarn.lock b/yarn.lock
index 8faa35e882..4b872317e3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -113,6 +113,18 @@ __metadata:
languageName: node
linkType: hard
+"@ai-sdk/openai-compatible@npm:^2.0.40":
+ version: 2.0.41
+ resolution: "@ai-sdk/openai-compatible@npm:2.0.41"
+ dependencies:
+ "@ai-sdk/provider": "npm:3.0.8"
+ "@ai-sdk/provider-utils": "npm:4.0.23"
+ peerDependencies:
+ zod: ^3.25.76 || ^4.1.8
+ checksum: 10c0/3f91ad098edfedff46d9fa14b015fa46e235cc460cfdf45f1fb3f5114baa625684436770993aa7b969dbbf5f835a640e062c75cbf3ae72bd746ce6a37f2636f2
+ languageName: node
+ linkType: hard
+
"@ai-sdk/openai@npm:^3.0.30":
version: 3.0.34
resolution: "@ai-sdk/openai@npm:3.0.34"
@@ -177,6 +189,19 @@ __metadata:
languageName: node
linkType: hard
+"@ai-sdk/provider-utils@npm:4.0.23":
+ version: 4.0.23
+ resolution: "@ai-sdk/provider-utils@npm:4.0.23"
+ dependencies:
+ "@ai-sdk/provider": "npm:3.0.8"
+ "@standard-schema/spec": "npm:^1.1.0"
+ eventsource-parser: "npm:^3.0.6"
+ peerDependencies:
+ zod: ^3.25.76 || ^4.1.8
+ checksum: 10c0/06e0aaf95eef47617d87709f78e321c87d26663bae16e68e9776a4bced8d78823d4c1514ac5e5e7dcb74f24a2e37152bc6b6eb1e31c9f0f77e54a020993c276a
+ languageName: node
+ linkType: hard
+
"@ai-sdk/provider@npm:2.0.1":
version: 2.0.1
resolution: "@ai-sdk/provider@npm:2.0.1"
@@ -60472,6 +60497,7 @@ __metadata:
"@ai-sdk/google": "npm:^3.0.30"
"@ai-sdk/mistral": "npm:^3.0.20"
"@ai-sdk/openai": "npm:^3.0.30"
+ "@ai-sdk/openai-compatible": "npm:^2.0.40"
"@ai-sdk/provider-utils": "npm:^4.0.15"
"@ai-sdk/xai": "npm:^3.0.57"
"@aws-sdk/client-lambda": "npm:3.1001.0"