@kindgi/adapter-model-anthropic
npm install @kindgi/adapter-model-anthropic · source
Anthropic ModelProvider for @kindgi/capabilities. Wraps the official @anthropic-ai/sdk client behind the framework's provider-neutral interface and calls the Anthropic Messages API. One provider exposes every model listed in its metadata.models[]; ModelCallInput.model picks the model per call.
Purpose
Section titled “Purpose”Translate between the framework's ModelCallInput / ModelCallResult and a non-streaming messages.create call:
-
systemmessages are lifted into the top-levelsystemparameter, each its own text block, in order.toolmessages becometool_resultblocks folded into user turns, and assistanttoolCallsbecometool_useblocks. -
Tool names are encoded
.→__on send and decoded on receive, because the Messages API rejects dots in tool names (acme.orders.lookup↔acme__orders__lookup). Tool ids must not contain a literal__. -
max_tokensis always sent, since Anthropic requires it:input.maxOutputTokens, else the model'sModelInfo.maxOutputTokens, else4096.temperatureis sent when set, andabortSignalis passed to the request. -
stop_reasonmapsend_turn/stop_sequence/pause_turn→stop,max_tokens→length,tool_use→tool-use,refusal→content-filter, anything else →stop. -
Cost accounting that includes prompt caching. Anthropic reports four counters (
input_tokens,output_tokens,cache_creation_input_tokens,cache_read_input_tokens), andcostUsdbills each at its own rate:(input × rate + cacheCreation × rate × creationMultiplier + cacheRead × rate × readMultiplier + output × outputRate) / 1000. The multiplier defaults match the 5-minute cache tier (creation1.25, read0.1). Claude Opus 5.5 and Sonnet 5.5 read at0.05: setpromptCacheReadMultiplier: 0.05in theircost(theanthropicpreset does).usage.promptTokensincludes cache writes and reads;usage.cacheReadTokensandusage.cacheWriteTokensreport them. -
Prompt caching. Anthropic caches only the prefixes a request marks with
cache_control, so the adapter marks up to three (withPromptCache), each with the 5-minute cache:- the last tool (the tool definitions);
- the first system block (the agent's prompt; later system blocks, such as retrieved context, change from turn to turn);
- the last block of the last message, when another call will send this prefix again: the call has tools (the next step of a tool loop) or the conversation has an earlier answer (its next turn). A one-off call (no tools, no earlier answer, e.g. a judge) leaves its message unmarked: writing a tail that's never read again would only cost more.
The next call in a turn then reads the prefix at the read rate and writes only what's new. A prefix shorter than the model's minimum (from 512 tokens on the Claude 5.5 models) isn't cached and costs nothing extra. How Anthropic keeps cached prompts, and their eligibility for zero data retention: Anthropic's prompt caching and API and data retention pages.
Exports
Section titled “Exports”anthropicAdapterEntry(ANTHROPIC_ADAPTER_ID) — theAdapterFactoryEntrya runtime registers.anthropicAdapterFactorybuilds the provider from a registration whosesecret_refnames its Anthropic API key (resolved on every call); without one it throws, andanthropicCheckConfig(input)reports the same problem (secret_ref) without building anything.createAnthropicProvider(options)— returns aModelProviderwhosemetadataisoptions.metadata.invoke()throws wheninput.modelis not one ofmetadata.models[].name.AnthropicProviderOptions:apiKey: string | (() => string | Promise<string>)— a static key, or a resolver called on everyinvoke(). The SDK client is cached and rebuilt only when the resolved key changes, so a rotated secret takes effect on the next call. A per-tenant registry can register one provider per tenant whose resolver reads that tenant's secret.metadata—ProviderMetadatawhosemodels[]areAnthropicModelInfo. Caller-supplied, because the API does not report pricing, context windows or features.baseURL?— override the API host (proxy, gateway, region routing).clientOptions?— other@anthropic-ai/sdkclient options (timeout,maxRetries,defaultHeaders,fetch, …);apiKeyandbaseURLare excluded.client?— an injected SDK client, used as-is;apiKey,baseURLandclientOptionsare then ignored. Useful in tests.
AnthropicModelInfo—ModelInfowhosecostalso acceptspromptCacheCreationMultiplier?andpromptCacheReadMultiplier?.- Cost helpers —
computeCostUsd(usage, rates),toFrameworkUsage(usage),CostRates,DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN(1.25),DEFAULT_CACHE_READ_MULTIPLIER(0.1). - Translation helpers —
toAnthropicMessages(messages),toAnthropicTools(tools),fromAnthropicResponse(response),mapStopReason(reason). ModelProvider— type re-export from@kindgi/capabilities.
Example
Section titled “Example”import { createProviderRegistry } from '@kindgi/capabilities';import { createAnthropicProvider } from '@kindgi/adapter-model-anthropic';
const anthropic = createAnthropicProvider({ // Resolved on every call; `readTenantSecret` stands for your secret store lookup. apiKey: () => readTenantSecret(tenantId, 'anthropic-api-key'), metadata: { id: 'anthropic', region: 'us-east-1', models: [ { name: 'claude-opus-4-7', contextWindow: 200_000, features: ['tool-use'], maxOutputTokens: 8_192, // Rates from the provider's published pricing; cache multipliers default to the 5-minute tier. cost: { promptUsdPer1kTokens: 0.005, completionUsdPer1kTokens: 0.025 }, }, ], },});
const { registry } = createProviderRegistry();registry.register(tenantId, anthropic);
const result = await anthropic.invoke({ model: 'claude-opus-4-7', messages: [ { role: 'system', content: 'You are the acme support assistant.' }, { role: 'user', content: 'Summarise order 1042 in one sentence.' }, ], maxOutputTokens: 256,});console.log(result.message.content, result.usage, result.costUsd);A single-key deployment passes apiKey: process.env.ANTHROPIC_API_KEY (checked for undefined first) instead of a resolver.
Non-goals
Section titled “Non-goals”- Streaming.
invoke()resolves with the complete response; streaming would need a differentModelProviderinterface. - Extended thinking.
ModelMessagehas no thinking field;thinkingblocks in responses are dropped. - Image inputs.
ModelMessagecontent is text only. - Structured output.
structuredOutputonModelCallInputis ignored. No Kindgi caller sends it today: an agent's typed output is checked by parse and repair on every provider, so the anthropic preset's models still declarestructured-output(they can follow a JSON schema natively). - Retry logic in the adapter. Retries and timeouts are the SDK client's (
clientOptions.maxRetries,clientOptions.timeout).
Related
Section titled “Related”@kindgi/capabilities—ModelProvider,ProviderMetadata, and the provider registry.@kindgi/adapter-model-openai-compat— the same interface for OpenAI-compatible endpoints.@kindgi/adapter-model-in-process— local models inside the Node.js process.