Anthropic (Claude) Integration
This guide shows how to use VersionR with the Anthropic Node.js SDK to manage and version your Claude prompts.
Installation
npm install versionr @anthropic-ai/sdkSetup
import Anthropic from '@anthropic-ai/sdk'
import { VersionR } from 'versionr'
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
const pd = new VersionR({ apiKey: process.env.VERSIONR_API_KEY })Basic usage
The Anthropic Messages API separates the system prompt from messages. VersionR handles this — check prompt.role to determine where to place the content.
const startTime = Date.now()
const prompt = await pd.get('analysis-assistant', { env: 'production' })
// Build messages based on role
const isSystem = prompt.role === 'system'
const response = await anthropic.messages.create({
model: prompt.model, // e.g. "claude-opus-4-6"
max_tokens: prompt.maxTokens ?? 1024,
temperature: prompt.temperature,
...(isSystem && { system: prompt.content }),
messages: isSystem
? [{ role: 'user', content: userMessage }]
: [{ role: prompt.role, content: prompt.content }, { role: 'user', content: userMessage }],
})
const output = response.content[0]?.type === 'text'
? response.content[0].text
: ''
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.input_tokens,
completion: response.usage.output_tokens,
},
})With variable substitution
const startTime = Date.now()
const rendered = await pd.render('code-reviewer', {
env: 'production',
variables: {
language: 'TypeScript',
code_snippet: sourceCode,
focus_area: 'security',
},
})
const response = await anthropic.messages.create({
model: rendered.model,
max_tokens: rendered.maxTokens ?? 2048,
temperature: rendered.temperature,
system: rendered.role === 'system' ? rendered.content : undefined,
messages: rendered.role === 'system'
? [{ role: 'user', content: 'Please review the code.' }]
: [{ role: rendered.role, content: rendered.content }],
})
const output = response.content[0]?.type === 'text'
? response.content[0].text
: ''
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.input_tokens,
completion: response.usage.output_tokens,
},
})Streaming
const rendered = await pd.render('writing-assistant', {
env: 'production',
variables: { topic: userTopic, tone: 'professional' },
})
const startTime = Date.now()
let fullOutput = ''
const stream = anthropic.messages.stream({
model: rendered.model,
max_tokens: rendered.maxTokens ?? 1024,
system: rendered.role === 'system' ? rendered.content : undefined,
messages: [{ role: 'user', content: userMessage }],
})
stream.on('text', (text) => {
fullOutput += text
process.stdout.write(text)
})
await stream.finalMessage()
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,
})Model names
VersionR stores the model name alongside the prompt version. When creating prompts in the dashboard, use the full Anthropic model ID:
| Model | ID |
|---|---|
| Claude Opus 4.6 | claude-opus-4-6 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 |
| Claude Haiku 4.5 | claude-haiku-4-5-20251001 |