Model Adapter (OpenAI / Gemini)
createOpenAIAdapter (@rejelly/adapter-openai) and createGeminiAdapter (@rejelly/adapter-gemini) wrap provider models into Rejelly's ModelAdapter and deliver the JSON Schema from promptAgent(schema) to the underlying model.
For the send-side contract of multimodal tool results, see Adapter · Multimodal Tool Results.
Creating a Model Adapter
OpenAI
import { createOpenAIAdapter } from '@rejelly/adapter-openai';
const model = createOpenAIAdapter({
modelId: 'gpt-5.6-luna',
apiKey: process.env.OPENAI_API_KEY,
schemaMode: 'json_schema',
});createOpenAIAdapter also works with OpenAI-compatible providers:
import { createOpenAIAdapter } from '@rejelly/adapter-openai';
const model = createOpenAIAdapter({
id: 'deepseek-chat',
provider: 'deepseek',
modelId: 'deepseek-chat',
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: 'https://api.deepseek.com',
schemaMode: 'json_object',
chatCompletionParams: {
temperature: 0.2,
},
requestOption: {
timeout: 60_000,
},
});Response-header and stream idle timeouts
requestOption.timeout is the OpenAI SDK's response-header wait budget. For streaming requests it stops counting once HTTP response headers arrive; it is not a total generation deadline. Gateways may delay headers until the first upstream SSE event.
Set streamIdleTimeoutMs separately to bound each wait for the next SDK protocol event after headers. It applies to both Chat Completions and Responses, resets on metadata events as well as content, and does not count time spent processing an event in the consumer. It is disabled when omitted. SSE comments alone do not count as SDK protocol events.
const model = createOpenAIAdapter({
modelId: 'gpt-5.6-luna',
requestOption: { timeout: 300_000, maxRetries: 0 },
streamIdleTimeoutMs: 300_000,
});Idle timeouts abort the upstream request and are classified as ModelCallError with code timeout; their message distinguishes a stalled stream from a response-header timeout. User cancellation remains cancellation.
Gemini
import { createGeminiAdapter } from '@rejelly/adapter-gemini';
const model = createGeminiAdapter({
modelId: 'gemini-2.5-pro',
apiKey: process.env.GEMINI_API_KEY,
schemaMode: 'json_schema',
});In Node environments, if apiKey is not explicitly passed, Gemini reads GEMINI_API_KEY or GOOGLE_API_KEY; in browser environments, it should be passed explicitly. Use generateContentParams to forward Gemini request parameters:
import { createGeminiAdapter } from '@rejelly/adapter-gemini';
const model = createGeminiAdapter({
modelId: 'gemini-2.5-flash',
schemaMode: 'prompt',
generateContentParams: {
temperature: 0.3,
},
});Using in an Agent
The created object is a Rejelly ModelAdapter and can be passed directly to createAgent({ model }), or injected uniformly via runWith's model registry.
import { createAgent, promptAgent } from '@rejelly/core';
import { createOpenAIAdapter } from '@rejelly/adapter-openai';
import { z } from 'zod';
const model = createOpenAIAdapter({
modelId: 'gpt-5.6-luna',
apiKey: process.env.OPENAI_API_KEY,
});
const AnswerSchema = z.object({
answer: z.string(),
});
export const AnswerAgent = createAgent({
id: 'answer',
model,
handler: async () => {
return await promptAgent(AnswerSchema);
},
});Cost Calculation
To have the Budget mechanism record real costs, provide calculateCost on the adapter. Return values use integer units, e.g., micro_usd.
import { createOpenAIAdapter } from '@rejelly/adapter-openai';
const model = createOpenAIAdapter({
modelId: 'gpt-5.6-luna',
apiKey: process.env.OPENAI_API_KEY,
calculateCost: (usage) => ({
micro_usd:
Math.ceil(usage.promptTokens * 1) +
Math.ceil(usage.completionTokens * 6),
}),
});Prompt Schema Injection
Choose the schema delivery method via schemaMode:
"prompt":Injects the schema into the system prompt — broadest compatibility (OpenAI default)."json_object": OpenAI Chat Completions usesresponse_format: { type: "json_object" }, OpenAI Responses uses the equivalenttext.format: { type: "json_object" }, and Gemini usesresponseMimeType: "application/json". The schema is still injected into the prompt for field constraints. Suitable for models with JSON mode but without strict schema support (e.g., DeepSeek)."json_schema":Native Structured Outputs (OpenAI strict / GeminiresponseSchema), where the model strictly enforces fields (Gemini default).