mrkeyoor.com_
Sat 19 Sept 15:54 UTC
npmAI / MLupdated 19 Sept 2026

@anthropic-ai/sdk review

@anthropic-ai/sdk is Anthropic's typed JavaScript client for the Claude API. It covers Messages, streaming, token counting, files, skills, and tool execution without making you assemble HTTP requests or parse server-sent events. Version 0.120.0 adds configuration for managed-agent web search and memory for self-hosted sandboxes. Our browser build failed because the package pulled in Node-only code, which matches the README's server-side focus and its default block on browser credentials.

36.5Mdownloads / wk
Verdict

Install it for a server-side TypeScript service that talks directly to Claude. Keep it out of browser bundles, pin the 0.x version, and use a multi-provider client if vendor switching is part of the design.

We installed it

Lab card: what happened when we installed @anthropic-ai/sdkScreenshot of @anthropic-ai/sdk documentation
Install✓ · 5s7 packages on disk · 15 MB
ImportESM import works · require() works · CommonJS package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @anthropic-ai/sdk install cleanly?

Yes. In a fresh container with an empty cache, npm install @anthropic-ai/sdk finished in 5 seconds, leaving 7 packages and 15 MB on disk. npm audit reported no known vulnerabilities.

Can @anthropic-ai/sdk run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @anthropic-ai/sdk work with both ESM and CommonJS?

Yes. Both import '@anthropic-ai/sdk' and require('@anthropic-ai/sdk') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does @anthropic-ai/sdk include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@anthropic-ai/sdk or ai: which should you use?

ai: Use it when the same application switches among Anthropic, OpenAI, Google, and other model providers. Install it for a server-side TypeScript service that talks directly to Claude.

When should you not use @anthropic-ai/sdk?

Your code runs only in a browser: the client blocks that runtime unless dangerouslyAllowBrowser is set because an Anthropic API key would be exposed

API stability3/5The core Messages call is easy to follow and both CommonJS require() and ESM import passed our check. The package remains at 0.120.0, though, and adjacent releases added files, skills, browser-use toolsets, web search configuration, and sandbox memory. That release pace gives users useful API coverage but makes version pinning and release-note review part of normal maintenance.
Docs4/5The repository README gives a minimal install, one Messages example, the supported runtime matrix, and explicit warnings for browsers, jsdom, and React Native. The linked platform documentation has the fuller API reference. The split is workable, though developers must leave the README for streaming, retries, errors, uploads, and tool helpers.
Maintenance5/5The repository was pushed on 2026-08-21 and the 0.120.0 release landed on 2026-08-19. The same release stream tracks new Claude API resources, while the repository also publishes separate Bedrock, Vertex, Foundry, AWS, and Google Cloud packages. That activity is current and first party, with the tradeoff that updates arrive often.
Ecosystem5/5The npm download endpoint recorded 33,874,669 downloads for the week ending 2026-08-22. The package ships its own TypeScript declarations, accepts Zod 3.25 or 4 as an optional peer for schema helpers, and supports Node, Deno, Bun, Cloudflare Workers, and Vercel Edge. React Native and browser-only applications remain clear gaps.

Use it if

  • Your Node, Bun, Deno, Worker, or Vercel Edge service calls Claude directly and you want request and response types bundled with the client
  • You need streamed text plus a final typed Message object after the stream closes
  • Your application uses Claude tools, files, token counting, or the new managed-agent web search configuration
  • You want API errors split into rate-limit, connection, authentication, and other status-specific classes
Skip it if

Setup reality

Our clean Node 22 install of 0.120.0 finished in 5 seconds. It left 7 packages using 15 MB on disk. The package itself has 2 direct dependencies, 1 peer dependency, and 11,896 KB unpacked. npm audit reported 0 known vulnerabilities. Both require() and ESM import worked, and the package includes TypeScript declarations.

Set ANTHROPIC_API_KEY on the server and new Anthropic() reads it by default. The README supports TypeScript 4.9 or newer, Node 20 LTS or newer, Deno 1.28+, Bun 1.0+, Cloudflare Workers, and Vercel Edge. Jest needs its node environment; jsdom is unsupported. React Native is also outside the supported list.

Browser bundling failed in our esbuild check because Node-only code entered the graph. The SDK disables browser use unless you pass dangerouslyAllowBrowser: true. That option removes a guard, not the credential exposure. Put the call behind your own authenticated endpoint. Zod is a peer dependency, so install it only when you use helpers that validate tool inputs or parsed output.

Streaming has two useful layers: event callbacks for deltas and finalMessage() for the completed response. The client retries selected connection failures, 408, 409, 429, and 5xx responses twice by default. A timeout applies to each attempt, so retries can make total wall time much longer than the timeout value. Pin 0.120.0 and read release notes before updating because the API surface moves quickly.

Patterns

Send a message create-message

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();
const message = await anthropic.messages.create({
  model: 'claude-opus-4-6',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Explain this stack trace.' }],
});

for (const block of message.content) {
  if (block.type === 'text') console.log(block.text);
}

The client reads ANTHROPIC_API_KEY by default. Message content is an array, so narrow each block by type before reading text.

Add system instructions add-system-prompt

const message = await anthropic.messages.create({
  model: 'claude-opus-4-6',
  max_tokens: 700,
  system: 'Return valid PostgreSQL and one sentence of explanation.',
  messages: [{ role: 'user', content: 'Find duplicate email addresses.' }],
});

The Messages API takes system at the top level. Do not insert a message with role set to system.

Stream text and collect the final message stream-text

const stream = anthropic.messages.stream({
  model: 'claude-opus-4-6',
  max_tokens: 2048,
  messages: [{ role: 'user', content: 'Draft a migration plan.' }],
});

stream.on('text', text => process.stdout.write(text));
const finalMessage = await stream.finalMessage();
console.log(finalMessage.usage.output_tokens);

finalMessage() waits for completion and returns the normal Message object, including usage.

Count tokens before generation count-input-tokens

const count = await anthropic.messages.countTokens({
  model: 'claude-opus-4-6',
  messages: [{ role: 'user', content: documentText }],
});

console.log(count.input_tokens);

Use the API's model-specific count when enforcing a request budget instead of applying a tokenizer built for another provider.

Send a JSON Schema tool define-tool

const response = await anthropic.messages.create({
  model: 'claude-opus-4-6',
  max_tokens: 1024,
  tools: [{
    name: 'lookup_order',
    description: 'Look up an order by id',
    input_schema: {
      type: 'object',
      properties: { id: { type: 'string' } },
      required: ['id'],
    },
  }],
  messages: [{ role: 'user', content: 'Where is order A-42?' }],
});

Your application still has to execute the named tool and send a tool_result block back unless it uses a tool-runner helper.

Continue after a tool call return-tool-result

const toolUse = response.content.find(block => block.type === 'tool_use');
if (!toolUse || toolUse.type !== 'tool_use') throw new Error('No tool call');

const next = await anthropic.messages.create({
  model: 'claude-opus-4-6', max_tokens: 1024, tools,
  messages: [...messages,
    { role: 'assistant', content: response.content },
    { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(order) }] },
  ],
});

Keep the assistant tool_use content in history and match tool_use_id exactly in the following tool_result.

Send a base64 image send-image

import { readFile } from 'node:fs/promises';

const data = (await readFile('chart.png')).toString('base64');
const message = await anthropic.messages.create({
  model: 'claude-opus-4-6', max_tokens: 800,
  messages: [{ role: 'user', content: [
    { type: 'image', source: { type: 'base64', media_type: 'image/png', data } },
    { type: 'text', text: 'Summarize the trend in this chart.' },
  ] }],
});

Set media_type to the file's real MIME type. The base64 data must not include a data URL prefix.

Branch on typed API errors handle-api-errors

try {
  await anthropic.messages.create(request);
} catch (error) {
  if (error instanceof Anthropic.RateLimitError) console.error('rate limited');
  else if (error instanceof Anthropic.APIConnectionError) console.error('network failure', error.cause);
  else if (error instanceof Anthropic.APIError) console.error(error.status, error.message);
  else throw error;
}

The client retries selected failures automatically. Application-level retries need a total deadline to avoid multiplying wait time.

Set retries and timeout configure-retries

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
  maxRetries: 1,
  timeout: 30_000,
});

await anthropic.messages.create(request, { maxRetries: 0, timeout: 10_000 });

Client values apply by default and request options override them. Timeout values are milliseconds.

Read response metadata inspect-response-headers

const { data: message, response } = await anthropic.messages
  .create(request)
  .withResponse();

console.log(response.headers.get('request-id'));
console.log(message.stop_reason);

withResponse() returns the parsed body and the underlying Response, which is useful when logging request IDs.

Iterate through every page paginate-results

for await (const item of anthropic.beta.skills.list({ limit: 20 })) {
  console.log(item.id, item.display_title);
}

Async iteration requests later pages as needed. Use the page object methods when you need explicit control over each request.

Enable browser calls only for non-secret credentials allow-browser-explicitly

const browserClient = new Anthropic({
  apiKey: shortLivedUserToken,
  dangerouslyAllowBrowser: true,
});

Do not place a normal Anthropic API key in shipped JavaScript. The option only disables the SDK's safety check.

Alternatives

PackageRegistryPick it when
ainpmUse it when the same application switches among Anthropic, OpenAI, Google, and other model providers.
openainpmUse the first-party client when the service is built around OpenAI APIs instead of Claude.
anthropicPyPIUse Anthropic's Python client when the calling service and its type checks live in Python.

More ai / ml guides

openai · mcp · huggingface-hub · @modelcontextprotocol/sdk · scikit-learn · tiktoken · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.