Skip to content

Anthropic

The AnthropicProvider module integrates the Anthropic Messages API with the Swift AI SDK. Its default anthropic instance is a native Provider V4 facade and supports text generation, streaming, reasoning, files, skills, and Anthropic provider-defined tools.

Add the package and both the high-level SDK and Anthropic products to your target:

Package.swift
dependencies: [
.package(
url: "https://github.com/teunlao/swift-ai-sdk",
from: "0.19.0"
)
],
targets: [
.target(
name: "YourTarget",
dependencies: [
.product(name: "SwiftAISDK", package: "swift-ai-sdk"),
.product(name: "AnthropicProvider", package: "swift-ai-sdk")
]
)
]

Set ANTHROPIC_API_KEY in the process environment. Authentication is loaded lazily when the first request is made, so constructing a model does not require the environment variable to be present yet.

Import the default V4 provider and create a model by ID:

import SwiftAISDK
import AnthropicProvider
let model = try anthropic("claude-sonnet-5")

Use createAnthropic(settings:) when you need custom provider settings:

let customAnthropic = createAnthropic(
settings: AnthropicProviderSettings(
baseURL: "https://proxy.example.com/v1",
apiKey: "your-api-key",
headers: ["x-application": "example"]
)
)
let model = try customAnthropic("claude-opus-4-8")

The settings are:

  • baseURL: API URL prefix. Defaults to https://api.anthropic.com/v1.
  • apiKey: value for the x-api-key header. Defaults to ANTHROPIC_API_KEY.
  • authToken: value for Authorization: Bearer. Use either apiKey or authToken, never both.
  • headers: additional request headers.
  • fetch: custom FetchFunction, useful for proxies, recording, and tests.
  • generateId: request ID generator used by provider internals.
  • name: provider name override.

The explicitly named createAnthropicProvider(settings:) factory remains available for code that must construct a legacy Provider V3 model. New code should use anthropic or createAnthropic(settings:).

The V4 facade exposes equivalent model factories:

let generic = try anthropic.languageModel(modelId: "claude-sonnet-5")
let chat = anthropic.chat("claude-sonnet-5")
let messages = anthropic.messages("claude-sonnet-5")

Pass any of them to the high-level generation APIs:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
prompt: "Write a vegetarian lasagna recipe for four people."
)
print(result.text)

Anthropic models also work with streamText, generateObject, and streamObject. See AI SDK Core for the shared generation contract.

Provider-specific options are passed under the anthropic key:

let options: ProviderOptions = [
"anthropic": [
"sendReasoning": true,
"toolStreaming": true,
"disableParallelToolUse": false
]
]

The Anthropic request parser supports:

  • sendReasoning: include prior reasoning content in the request. Defaults to true.
  • structuredOutputMode: outputFormat, jsonTool, or auto.
  • thinking: adaptive, budget-based, or disabled thinking configuration.
  • effort: low, medium, high, xhigh, or max.
  • disableParallelToolUse: force at most one tool call at a time.
  • toolStreaming: enable streamed tool inputs and structured output. Defaults to true.
  • cacheControl: request-level cache control.
  • metadata: request metadata such as an opaque userId.
  • mcpServers: Anthropic server-side MCP connectors.
  • container: container ID and Anthropic or custom skills.
  • taskBudget: advisory total and remaining token budget.
  • speed: fast or standard.
  • inferenceGeo: us or global.
  • fallbacks: server-side fallback model chain.
  • contextManagement: context editing and compaction rules.
  • anthropicBeta: extra beta header values not inferred by the provider.

Tool input streaming and structured output streaming are enabled by default. Disable them for a request with:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
prompt: "Return a compact project status.",
providerOptions: [
"anthropic": [
"toolStreaming": false,
"structuredOutputMode": "outputFormat"
]
]
)

Anthropic effort controls how much work Claude spends across reasoning, normal text, and tool calls. xhigh and max are distinct levels. The generic V4 reasoning enum ends at xhigh; the Anthropic-only max level must be passed as the provider effort option.

Use the normalized V4 setting when portable reasoning control is preferred:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
prompt: "Design a lock-free queue and explain its memory ordering.",
settings: CallSettings(reasoning: .xhigh)
)

Use the provider option for the actual Anthropic maximum:

let result = try await generateText(
model: try anthropic("claude-opus-4-8"),
prompt: "Find and prove the strongest invariant for this protocol.",
providerOptions: [
"anthropic": ["effort": "max"]
]
)

An explicit provider effort takes precedence over the normalized reasoning setting. This lets a request use CallSettings(reasoning: .high) as a portable default while selecting Anthropic max explicitly.

Modelxhighmax
claude-sonnet-5
claude-fable-5
claude-opus-4-8
claude-opus-4-7
claude-opus-4-6
claude-sonnet-4-6

For claude-opus-4-6 and claude-sonnet-4-6, normalized .xhigh maps to Anthropic max and returns a compatibility warning. Older budget-thinking models map normalized levels to a token budget instead. See Anthropic’s effort documentation for the provider’s current model matrix.

Current frontier models support adaptive thinking. Claude chooses whether and how much to reason for each request:

let result = try await generateText(
model: try anthropic("claude-opus-4-8"),
prompt: "How many people will live in the world in 2040?",
providerOptions: [
"anthropic": [
"thinking": [
"type": "adaptive",
"display": "summarized"
],
"effort": "max"
]
]
)
print(result.reasoningText as Any)
print(result.reasoning)
print(result.text)

On models whose default thinking display is omitted, use display: "summarized" when visible reasoning progress is required.

Earlier Claude models use an explicit thinking-token budget:

let result = try await generateText(
model: try anthropic("claude-sonnet-4-5-20250929"),
prompt: "Derive a capacity plan for this service.",
providerOptions: [
"anthropic": [
"thinking": [
"type": "enabled",
"budgetTokens": 12_000
]
]
]
)

Do not combine manual sampling controls such as temperature, topP, or topK with adaptive-thinking models that reject those controls. The provider emits warnings or omits incompatible settings according to the model’s capability contract.

Fast mode, task budgets, data residency, and fallbacks use the same provider options boundary:

let result = try await generateText(
model: try anthropic("claude-opus-4-8"),
prompt: "Compare Rust and Go for a long-running CLI agent.",
providerOptions: [
"anthropic": [
"taskBudget": [
"type": "tokens",
"total": 400_000,
"remaining": 215_000
],
"inferenceGeo": "us",
"fallbacks": [
["model": "claude-fable-5"]
]
]
]
)

taskBudget is advisory; it does not replace maxOutputTokens. The speed option accepts fast or standard on models that expose fast mode. A safety classifier refusal is normalized to the content-filter finish reason, and provider stop details remain available in Anthropic provider metadata.

Set cache breakpoints on system messages, user messages, content parts, or tools with Anthropic provider options:

let messages: [ModelMessage] = [
.system(SystemModelMessage(
content: "You are a Swift concurrency expert.",
providerOptions: [
"anthropic": [
"cacheControl": ["type": "ephemeral", "ttl": "1h"]
]
]
)),
.user(UserModelMessage(content: .parts([
.text(TextPart(text: "Review this failure:")),
.text(TextPart(
text: longFailureLog,
providerOptions: [
"anthropic": ["cacheControl": ["type": "ephemeral"]]
]
))
])))
]
let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
messages: messages
)

Cache creation and read token counts are returned in Anthropic provider metadata. Anthropic still applies its model-specific minimum cacheable prompt lengths.

Anthropic tools are exposed from anthropic.tools. The Swift factory names are camelCase and include the provider version:

let tools: [String: Tool] = [
"web_search": anthropic.tools.webSearch20260209(
AnthropicWebSearchOptions(maxUses: 5)
),
"web_fetch": anthropic.tools.webFetch20260209(
AnthropicWebFetchOptions(
maxUses: 2,
citationsEnabled: true,
maxContentTokens: 20_000
)
),
"code_execution": anthropic.tools.codeExecution20260120()
]

Available factories include:

  • bash20241022 and bash20250124
  • textEditor20241022, textEditor20250124, and textEditor20250728
  • computer20241022, computer20250124, and computer20251124
  • webSearch20250305 and webSearch20260209
  • webFetch20250910 and webFetch20260209
  • codeExecution20250522, codeExecution20250825, and codeExecution20260120
  • memory20250818
  • advisor20260301
  • toolSearchRegex20251119 and toolSearchBm2520251119

Choose the tool version supported by the selected Claude model. For example:

let editor = anthropic.tools.textEditor20250728(
AnthropicTextEditor20250728Args(maxCharacters: 10_000)
)
let computer = anthropic.tools.computer20251124(
AnthropicComputerOptions(
displayWidthPx: 1920,
displayHeightPx: 1080,
enableZoom: true
)
)
let advisor = anthropic.tools.advisor20260301(
AnthropicAdvisor20260301Options(
model: "claude-opus-4-8",
maxUses: 3
)
)

Provider-defined tools execute on Anthropic infrastructure unless their contract explicitly describes a client-side implementation. Use the exact tool dictionary name documented by each factory, such as code_execution, web_search, computer, or advisor.

Tool search lets Claude discover deferred tools without loading all schemas at once:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
tools: [
"tool_search": anthropic.tools.toolSearchBm2520251119(),
"weather": weatherTool.eraseToTool()
],
prompt: "Find the weather tool and use it.",
providerOptions: nil
)

Mark individual deferred tools with providerOptions: ["anthropic": ["deferLoading": true]] when constructing them. Programmatic tool calling similarly uses the tool-level allowedCallers provider option.

Anthropic can connect to remote MCP servers within a request:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
prompt: "Call the remote echo tool with hello.",
providerOptions: [
"anthropic": [
"mcpServers": [[
"type": "url",
"name": "echo",
"url": "https://example.com/mcp",
"authorizationToken": mcpToken,
"toolConfiguration": [
"enabled": true,
"allowedTools": ["echo"]
]
]]
]
]
)

Use the current code execution tool for a provider-managed execution environment:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
tools: [
"code_execution": anthropic.tools.codeExecution20260120()
],
prompt: "Calculate the mean and standard deviation of 1 through 10."
)

Upload a file through the V4 provider, then pass the returned provider reference into a typed FilePart. Set containerUpload when the file should be mounted in the code execution container:

let upload = try await uploadFile(
api: anthropic,
data: DataContentOrURL.data(
try Data(contentsOf: URL(fileURLWithPath: "./data.csv"))
),
mediaType: "text/csv",
filename: "data.csv"
)
let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
tools: [
"code_execution": anthropic.tools.codeExecution20260120()
],
messages: [
.user(UserModelMessage(content: .parts([
.text(TextPart(text: "Analyze this CSV file.")),
.file(FilePart(
data: .reference(upload.providerReference),
mediaType: "text/csv",
filename: "data.csv",
providerOptions: [
"anthropic": ["containerUpload": true]
]
))
])))
]
)

Without containerUpload, an Anthropic provider reference is serialized as a normal Files API source. The provider automatically attaches the Files API beta header for referenced files.

Built-in Anthropic skills are selected through the request container and require code execution:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
tools: [
"code_execution": anthropic.tools.codeExecution20260120()
],
prompt: "Create a five-slide presentation about renewable energy.",
providerOptions: [
"anthropic": [
"container": [
"skills": [[
"type": "anthropic",
"skillId": "pptx",
"version": "latest"
]]
]
]
]
)

Custom skills can be uploaded directly through the V4 provider:

let uploadedSkill = try await uploadSkill(
api: anthropic,
files: [
SkillsV4File(
path: "SKILL.md",
content: .text("# Data review\nAnalyze the supplied dataset.")
)
],
displayTitle: "Data review"
)

Use the returned Anthropic skill identity in a custom container skill entry.

Pass a PDF URL, bytes, or an uploaded provider reference in a typed file part:

let result = try await generateText(
model: try anthropic("claude-sonnet-5"),
messages: [
.user(UserModelMessage(content: .parts([
.text(TextPart(
text: "What is an embedding model according to this document?"
)),
.file(FilePart(
data: .url(URL(
string: "https://example.com/guide.pdf"
)!),
mediaType: "application/pdf",
filename: "guide.pdf"
))
])))
]
)

For local PDF data, use DataContentOrURL.data(pdfData). For an upload result, use .reference(upload.providerReference).

ModelImage InputObject GenerationTool UsageComputer UseWeb SearchTool SearchCompaction
claude-sonnet-5
claude-fable-5
claude-opus-4-8
claude-opus-4-7
claude-opus-4-6
claude-sonnet-4-6
claude-opus-4-5
claude-haiku-4-5
claude-sonnet-4-5

The model list is open-ended: pass any Anthropic model ID as a string when a new provider model becomes available. The helpers above document the model families audited by this SDK baseline.