GuidesOpenAI

OpenAI Integration

This guide shows how to use VersionR alongside the OpenAI Node.js SDK. The pattern is the same regardless of which OpenAI model you use.


Installation

npm install versionr openai

Setup

import OpenAI from 'openai'
import { VersionR } from 'versionr'
 
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
const pd = new VersionR({ apiKey: process.env.VERSIONR_API_KEY })

Basic usage with pd.get()

Fetch the prompt and pass it directly to the Chat Completions API:

const startTime = Date.now()
 
const prompt = await pd.get('support-responder', { env: 'production' })
 
const response = await openai.chat.completions.create({
  model: prompt.model,           // versioned model name
  temperature: prompt.temperature,
  messages: [
    { role: prompt.role, content: prompt.content },
    { role: 'user', content: userMessage },
  ],
})
 
const output = response.choices[0]?.message.content ?? ''
 
await pd.log({
  promptId: prompt.promptId,
  promptSlug: prompt.promptSlug,
  versionId: prompt.versionId,
  versionNumber: prompt.versionNumber,
  environment: 'production',
  renderedPrompt: prompt.content,
  output,
  latencyMs: Date.now() - startTime,
  tokens: {
    prompt: response.usage?.prompt_tokens ?? 0,
    completion: response.usage?.completion_tokens ?? 0,
  },
})

With variable substitution

Use pd.render() when your prompt has {{variable}} slots:

const startTime = Date.now()
 
const rendered = await pd.render('onboarding-email', {
  env: 'production',
  variables: {
    user_name: user.name,
    plan_name: user.plan,
    trial_days: String(user.trialDays),
  },
})
 
const response = await openai.chat.completions.create({
  model: rendered.model,
  temperature: rendered.temperature,
  messages: [
    { role: rendered.role, content: rendered.content },
  ],
})
 
const output = response.choices[0]?.message.content ?? ''
 
await pd.log({
  promptId: rendered.promptId,
  promptSlug: rendered.promptSlug,
  versionId: rendered.versionId,
  versionNumber: rendered.versionNumber,
  environment: 'production',
  renderedPrompt: rendered.rendered,
  output,
  latencyMs: Date.now() - startTime,
  tokens: {
    prompt: response.usage?.prompt_tokens ?? 0,
    completion: response.usage?.completion_tokens ?? 0,
  },
})

Streaming

VersionR works with OpenAI streaming — fetch the prompt first, then stream the response:

const rendered = await pd.render('chat-assistant', {
  env: 'production',
  variables: { context: pageContext },
})
 
const stream = await openai.chat.completions.create({
  model: rendered.model,
  temperature: rendered.temperature,
  stream: true,
  messages: [
    { role: rendered.role, content: rendered.content },
    { role: 'user', content: userMessage },
  ],
})
 
let fullOutput = ''
const startTime = Date.now()
 
for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta.content ?? ''
  fullOutput += delta
  process.stdout.write(delta)
}
 
// Log after stream completes
await pd.log({
  promptId: rendered.promptId,
  promptSlug: rendered.promptSlug,
  versionId: rendered.versionId,
  versionNumber: rendered.versionNumber,
  environment: 'production',
  renderedPrompt: rendered.rendered,
  output: fullOutput,
  latencyMs: Date.now() - startTime,
  // Note: usage is not available mid-stream with all models
})

Structured outputs

VersionR is compatible with OpenAI’s structured output / response format feature:

const rendered = await pd.render('data-extractor', {
  env: 'production',
  variables: { document: rawText },
})
 
const response = await openai.chat.completions.create({
  model: rendered.model,
  temperature: rendered.temperature,
  response_format: { type: 'json_object' },
  messages: [
    { role: rendered.role, content: rendered.content },
  ],
})
 
const data = JSON.parse(response.choices[0]?.message.content ?? '{}')

MIT 2026 © Nextra.