Anthropic Reference
Walkthrough of the real Anthropic provider leaf
Anthropic Reference
Use self/subcortex/providers/src/providers/anthropic/ as the reference leaf for structure, exports, and defensive parsing. Treat Anthropic's wire protocol details as provider-specific unless your provider actually implements the Anthropic Messages API.
File Walkthrough
| File | Role |
|---|---|
definition.ts | Re-exports ANTHROPIC_PROVIDER_DEFINITION as providerDefinition |
implementation.ts | Owns the provider class, default endpoint/model, credential handling, request execution, streaming, and metadata constant |
adapter.ts | Exports providerAdapter, anthropicAdapter, and createAnthropicAdapter(...) |
provider.ts | Exports providerFactory for runtime construction |
index.ts | Re-exports the leaf public surface; required by leaf validation |
Definition Shape
Anthropic's leaf keeps metadata with the implementation constants and re-exports it through definition.ts:
export {
ANTHROPIC_PROVIDER_DEFINITION as providerDefinition,
} from './implementation.js';The metadata constant uses the typed definition contract:
export const ANTHROPIC_PROVIDER_DEFINITION = {
vendorKey: 'anthropic',
displayName: 'Anthropic',
providerType: 'text',
providerClass: 'remote_text',
protocol: 'anthropic-messages',
adapterKey: 'anthropic',
defaultEndpoint: DEFAULT_ENDPOINT,
defaultModelId: DEFAULT_MODEL_ID,
auth: {
envVar: 'ANTHROPIC_API_KEY',
vaultKeyNamespace: 'anthropic',
header: {
name: 'x-api-key',
scheme: 'raw',
},
required: true,
purpose: 'api_key',
},
headers: {
'anthropic-version': ANTHROPIC_VERSION,
},
modelListEndpoint: '/v1/models',
modelListFormat: 'anthropic-models',
capabilities: {
streaming: true,
cacheControl: true,
extendedThinking: true,
nativeToolUse: true,
modelListing: true,
},
isLocal: false,
} as const satisfies ProviderDefinitionLeaf;Copy the shape, not the values. Your provider needs its own vendorKey, protocol, adapter key, endpoint, default model, auth metadata, and capabilities. Do not hand-author wellKnownProviderId; it is derived by the provider registry.
For API-key providers, auth.header tells Settings and the shared-server how to inject the key for health checks and model discovery. modelListEndpoint and modelListFormat opt the provider into dynamic model discovery; Anthropic uses the anthropic-models response shape.
Adapter Shape
Anthropic exports a stateless adapter module with defineProviderAdapter(...):
export const providerAdapter = defineProviderAdapter({
adapterKey: 'anthropic',
displayName: 'Anthropic',
protocol: 'anthropic-messages',
capabilities: ANTHROPIC_CAPABILITIES,
create(options) {
return createAnthropicAdapter(options?.log);
},
});Inside createAnthropicAdapter(...), formatRequest(...) translates canonical prompt/context/tool input into Anthropic request shape, and parseResponse(...) translates provider output back into ParsedModelOutput.
parseResponse(...) must not throw. Anthropic catches parse errors, logs them when a log channel exists, and returns a text fallback.
Factory Shape
provider.ts is small and stable:
export const providerFactory = {
vendorKey: 'anthropic',
create(config, options) {
return new AnthropicProvider(config, { apiKey: options?.apiKey });
},
} as const satisfies ProviderFactoryModule;Factory code constructs the concrete IModelProvider from runtime config and resolved credentials. It should not add central runtime branches elsewhere for a normal provider addition.
Anthropic-Only Behavior
Do not copy these details unless your provider documents the same semantics:
- The
anthropic-versionheader. - Messages API content block shapes.
cache_controlsystem segment handling.- Extended thinking blocks.
- Anthropic tool schema normalization and top-level combinator flattening.
- Anthropic stream event parsing.
The reusable lesson is the leaf shape: typed metadata, stateless adapter module, factory module, non-throwing response parsing, and tests that prove the provider's real API shape.