Beta . Ortha CMS is in public beta. Every plan is free until it ends.
Features Ortha CMS on GitHub

Claude (Anthropic)

Copilot plugin @orthacms/copilot-server@orthacms/copilot-admin

Native Claude — the default for tool-heavy work, and the one SDK dependency.

Documents 0.13.1 Updated Edit this page Report a problem

On this page

A ModelProvider over Anthropic’s own SDK. It is the only package in the copilot allowed to import a vendor SDK.

Install

npm install @orthacms/copilot-provider-anthropic

Configure

# .env
COPILOT_ENABLED=true
# setting it registers the backend
ANTHROPIC_API_KEY=sk-ant-...
COPILOT_ANTHROPIC_MODELS=claude-opus-5,claude-sonnet-5,claude-haiku-4-5
# optional gateway / proxy
ANTHROPIC_BASE_URL=
VariableDefaultNotes
ANTHROPIC_API_KEYunsetUnset = no claude in the picker at all
COPILOT_ANTHROPIC_MODELSreference: claude-opus-5,claude-sonnet-5,claude-haiku-4-5; generated app: claude-sonnet-5First is the default
ANTHROPIC_BASE_URLunsetReference server only. In a generated app, add baseUrl to config/copilot-anthropic.ts

The reference server, apps/server/config/copilot.ts:

const anthropicApiKey = readEnv('ANTHROPIC_API_KEY');

claude: when(anthropicApiKey, () =>
    defined({
        apiKey: anthropicApiKey as string,
        models: readList(
            'COPILOT_ANTHROPIC_MODELS',
            'claude-opus-5,claude-sonnet-5,claude-haiku-4-5'
        ),
        baseUrl: readEnv('ANTHROPIC_BASE_URL')
    })
),

A generated app has the same in config/copilot-anthropic.ts:

import type { AnthropicProviderConfig } from '@orthacms/copilot-provider-anthropic';
import { readEnv, readList } from '@orthacms/utils-server';

export function anthropicProvider(): AnthropicProviderConfig | undefined {
    const apiKey = readEnv('ANTHROPIC_API_KEY');
    if (!apiKey) return undefined;
    return { apiKey, models: readList('COPILOT_ANTHROPIC_MODELS', 'claude-sonnet-5') };
}

All options

AnthropicProviderConfig:

OptionDefaultNotes
apiKeyrequiredNever leaves the server
modelsrequiredNon-empty. First is the default
baseUrlAnthropic APIGateway, proxy or regional endpoint
effortAPI default (high)low | medium | high | xhigh | max
maxRetriesSDK’s 2On 429, 5xx, connection errors
timeoutMsSDK’s 10 minutesPer request
promptCachingtrueTurn off only for a gateway that rejects cache_control

Register

// apps/server/src/plugins.ts
import { createAnthropicProvider } from '@orthacms/copilot-provider-anthropic';

const { claude } = config.plugins.copilot.providers;

CopilotPlugin({
    providers: claude
        ? [{ name: 'claude', provider: createAnthropicProvider(claude) }]
        : [],
    config: config.plugins.copilot
});

Or with options that have no variable:

createAnthropicProvider({
    apiKey: process.env.ANTHROPIC_API_KEY!,
    models: ['claude-sonnet-5', 'claude-haiku-4-5'],
    effort: 'medium',
    timeoutMs: 120_000
});

Verify

curl -s -b cookies.txt http://localhost:3000/api/copilot/models
# {"items":[{"provider":"claude","model":"claude-opus-5"},
#           {"provider":"claude","model":"claude-sonnet-5"}, ...]}

No claude rows means the key was not read. Sign-in and a streamed run are shown on the copilot page.

Behaviour worth knowing

  • Unknown model = error, no request. A run naming a model outside models fails with UnknownModelError. It never falls back to the default.
  • Lazy client. The SDK client is built on first use, so an unused adapter never fails a boot.
  • Capabilities are probed from the Models API and cached per model. If the probe fails: 200,000-token context, 8,192 output tokens, vision and tool calling. A failed probe is not cached.
  • No thinking config is sent and no sampling parameters. Use effort.
  • Prompt caching: one breakpoint at the end of the system prompt, up to three rolling through the conversation.