Migrate from the Anthropic SDK
Moving from the official @anthropic-ai/sdk package to ORXA: LLM-SDK is mechanical. You
replace the client construction and the call site; your prompts, tools, and schemas stay
the same — and the same code now also runs OpenAI, Google, and xAI by changing one string.
Install
Section titled “Install”npm install @combycode/llm-sdkBasic completion
Section titled “Basic completion”Before:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });const msg = await client.messages.create({ model: 'claude-sonnet-4.6', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello' }],});console.log(msg.content[0].type === 'text' ? msg.content[0].text : '');After:
import { complete } from '@combycode/llm-sdk';
const { text } = await complete({ model: 'anthropic/claude-sonnet-4.6', apiKey: process.env.ANTHROPIC_API_KEY, prompt: 'Hello',});console.log(text);The model id becomes anthropic/<model>. max_tokens is no longer required — ORXA
defaults it (set maxTokens to override). The response is { text, parsed?, response },
so no more content[0].type === 'text' narrowing. Token counts are on response.usage
(response.usage.inputTokens, response.usage.outputTokens).
System prompt
Section titled “System prompt”Anthropic takes system as a top-level field; so does ORXA:
Before:
const msg = await client.messages.create({ model: 'claude-sonnet-4.6', max_tokens: 1024, system: 'You are terse.', messages: [{ role: 'user', content: 'Hello' }],});After:
const { text } = await complete({ model: 'anthropic/claude-sonnet-4.6', system: 'You are terse.', prompt: 'Hello',});Multi-turn
Section titled “Multi-turn”Pass a Message[] as the prompt:
const { text } = await complete({ model: 'anthropic/claude-sonnet-4.6', prompt: [ { role: 'user', content: 'Hi' }, { role: 'assistant', content: 'Hello!' }, { role: 'user', content: 'What did I just say?' }, ],});For managed conversations and layered context, see Multi-turn and Layered context.
Streaming
Section titled “Streaming”Before:
const stream = client.messages.stream({ model: 'claude-sonnet-4.6', max_tokens: 1024, messages: [{ role: 'user', content: 'Count to 5.' }],});for await (const event of stream) { if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') { process.stdout.write(event.delta.text); }}After — one event type, no nested narrowing:
import { createLLM } from '@combycode/llm-sdk';
const llm = createLLM({ model: 'anthropic/claude-sonnet-4.6', apiKey: process.env.ANTHROPIC_API_KEY });for await (const ev of llm.stream('Count to 5.')) { if (ev.type === 'text') process.stdout.write(ev.text);}See Streaming.
Tool calling
Section titled “Tool calling”Before — define an input_schema, then read tool_use blocks, run them, append
tool_result blocks, and call again:
const msg = await client.messages.create({ model: 'claude-sonnet-4.6', max_tokens: 1024, messages: [{ role: 'user', content: 'Weather in Paris?' }], tools: [{ name: 'get_weather', description: 'Get weather for a city', input_schema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] }, }],});// ...find tool_use blocks, execute, append tool_result, loopAfter — defineTool carries the executor, complete() runs the loop:
import { complete, defineTool } from '@combycode/llm-sdk';
const getWeather = defineTool({ name: 'get_weather', description: 'Get weather for a city', params: { city: 'string' }, execute: async ({ city }) => `Sunny in ${city}`,});
const { text } = await complete({ model: 'anthropic/claude-sonnet-4.6', prompt: 'Weather in Paris?', tools: [getWeather],});See Single tool call and Multi-step loop.
Structured / JSON output
Section titled “Structured / JSON output”Anthropic has no native JSON-schema response mode — you typically prompt for JSON and parse
by hand. ORXA gives you the same structured.schema option as every other provider:
const { parsed } = await complete({ model: 'anthropic/claude-sonnet-4.6', prompt: 'Extract name and age: John is 30', structured: { schema: { type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' } }, required: ['name', 'age'], }, },});console.log(parsed); // { name: 'John', age: 30 }If the model returns invalid JSON, complete() throws — wrap in try/catch to retry. See
Structured output.
Extended thinking
Section titled “Extended thinking”Before, Anthropic’s thinking block; in ORXA, a unified thinking option:
const llm = createLLM({ model: 'anthropic/claude-sonnet-4.6', apiKey: process.env.ANTHROPIC_API_KEY });const res = await llm.complete('Solve this step by step...', { thinking: { mode: 'auto', effort: 'high' },});console.log(res.thinking, res.text);See Reasoning.
What changes, what stays the same
Section titled “What changes, what stays the same”| Official SDK | ORXA | |
|---|---|---|
| Model id | 'claude-sonnet-4.6' | 'anthropic/claude-sonnet-4.6' |
max_tokens | required | optional (defaulted) |
| Response text | content[0].text (after narrowing) | result.text |
| Token usage | usage.input_tokens | response.usage.inputTokens |
| Tool loop | manual | run by complete() |
| JSON schema mode | none (prompt + parse) | structured.schema |
| Switch provider | new SDK + new shapes | change the model string |
Next: Models & providers · Provider routing & fallback · Cost tracking.