anthropic

js/ai/model/anthropic.ts

fino:ai/model/anthropic — Anthropic provider adapter for the shared Model.

Anthropic Messages API reference: https://docs.anthropic.com/en/api/messages

anthropic() returns a provider-neutral Model backed by Anthropic's Messages API. anthropicProvider() returns a discovery-capable provider that calls Anthropic's GET /v1/models endpoint and can construct models from discovered ids. Both paths translate Fino message parts into Anthropic content blocks, map server-sent events into StreamEvent values, normalize usage and stop reasons, and expose native JSON Schema response-format support through model capabilities.

Defaults and limits

apiKey defaults to ANTHROPIC_API_KEY, baseUrl defaults to the public Anthropic API, and model defaults to claude-opus-4-8. The adapter supports text, image, document, tool-use, and tool-result content parts. Anthropic does not provide a native embeddings endpoint through this adapter; embed() rejects with a clear error. Use an embeddings-capable provider for memory or semantic-similarity workflows.

Pass a custom client for tests, proxies, or runtimes that need their own HTTP transport. This adapter does not retry; retry and fallback policy belong to fino:ai/agent.

import { agent } from 'fino:ai/agent';
import { anthropicProvider } from 'fino:ai/model/anthropic';

const [info] = await anthropicProvider().listModels();
const bot = agent({
  model: await info.create(),
  instructions: 'Prefer explicit assumptions.',
});

const result = await bot.generate('Review this migration plan.');
console.log(result.text);

Functions

function anthropicProvider(opts: ProviderOptions = {}): ModelProvider

Create a discovery-capable Anthropic model provider.

Options passed here become the defaults for every model the provider constructs: apiKey (defaults to the ANTHROPIC_API_KEY environment variable), baseUrl, extra headers, maxTokens, temperature, topP, and provider-specific providerOptions. createModel() accepts per-model overrides that are layered on top of those defaults.

listModels() calls GET /v1/models on baseUrl — the public Anthropic API origin by default — and returns one ModelInfo per discovered id, carrying the raw listing entry in metadata and a create() closure that delegates to createModel(). If the endpoint responds 404, common for Anthropic-compatible proxies that only implement /v1/messages, listing throws ModelListingUnsupportedError; any other non-2xx response throws ModelError with the HTTP status and body.

Throws if no API key is passed and ANTHROPIC_API_KEY is unset.

import { anthropicProvider } from 'fino:ai/model/anthropic';

const provider = anthropicProvider({ maxTokens: 2048 });

const models = await provider.listModels();
const opus = models.find((info) => info.id.startsWith('claude-opus'));
const model = await opus!.create({ temperature: 0.2 });

const result = await model.generate({
  messages: [{ role: 'user', content: 'Summarize the release notes.' }],
});
console.log(result.text, result.usage.outputTokens);

function anthropic(opts: ProviderOptions = {}): Model

Create an Anthropic-backed Model in one call.

model selects the Anthropic model id and defaults to claude-opus-4-8. apiKey defaults to the ANTHROPIC_API_KEY environment variable; the call throws immediately when neither is available. Anthropic requires max_tokens on every request, so the adapter fills in maxTokens (default

  1. whenever a request does not set its own. temperature, topP, extra rs, and baseUrl set per-model defaults, and fields under derOptions.anthropic are merged verbatim into the request body — the hatch for Anthropic parameters the neutral request shape does not

The returned model supports generate() for buffered responses and stream() for incremental StreamEvent values — text deltas, tool-call assembly, and usage including cache read/creation token counts. Tool calling works with every toolChoice mode, and responseFormat with type: 'json_schema' maps to Anthropic's native structured-output support. Non-2xx responses from either path reject with ModelError carrying the HTTP status and body. embed() always rejects: Anthropic exposes no embeddings endpoint through this adapter.

Override client in tests or custom runtimes that provide their own HTTP transport.

import { anthropic } from 'fino:ai/model/anthropic';

const model = anthropic({ model: 'claude-opus-4-8', maxTokens: 8192 });

const stream = model.stream({
  system: 'You are a terse release-note writer.',
  messages: [{ role: 'user', content: 'Draft notes for the 1.4 release.' }],
});
let text = '';
for await (const event of stream) {
  if (event.type === 'text_delta') text += event.text;
}
const result = await stream.result();
console.log(text, result.stopReason, result.usage.outputTokens);