The complete Swift platform for Claude AI. SDK, agents, memory, and UI — everything you need to build AI-powered apps on Apple platforms.
Every AI agent framework is Python or TypeScript. LangGraph, CrewAI, Claude Agent SDK, OpenAI Agents SDK — none of them work in Swift. If you're building an iOS app, a macOS tool, or a visionOS experience and you want agentic AI, your options have been: shell out to Python, hand-roll your own loop, or give up.
ClaudeSwift changes that. Four libraries, one package, zero external dependencies:
| Library | What it does |
|---|---|
| ClaudeSwift | Full Claude API SDK — messages, streaming, vision, tools, sessions |
| MemoryKit | RAG pipeline, vector search, knowledge bases |
| AgentKit | Agent framework — ReAct, plan-and-execute, multi-agent, tool system |
| AgentKitUI | SwiftUI components — chat views, activity timelines, tool inspectors |
Swift has actors, structured concurrency, and Sendable — the best concurrency primitives of any mainstream language. An agent framework built on these isn't a port of a Python library. It's something new.
- Every agent is an actor — thread-safe by default, no locks, no races
- The tool registry is an actor — concurrent tool execution without data corruption
- Events stream through AsyncStream — native backpressure, cancellation, composition
- UI binds via @Observable — one line to connect an agent to SwiftUI
No other agent framework can say this because no other agent framework is written in Swift.
// Package.swift
dependencies: [
.package(url: "https://github.com/ClaudeSwift/ClaudeSwiftSDK.git", from: "1.0.0")
]
// Pick what you need
.target(name: "MyApp", dependencies: [
"ClaudeSwift", // Just the SDK
"MemoryKit", // + RAG and vector search
"AgentKit", // + Agent framework
"AgentKitUI", // + SwiftUI components
])Or in Xcode: File > Add Package Dependencies > enter the repository URL.
Full coverage of the Anthropic Claude API with zero compromises.
import ClaudeSwift
let client = ClaudeClient(apiKey: "your-api-key")
let response = try await client.messages.create(
model: .sonnet4_5,
maxTokens: 1024,
messages: [.user("What is the capital of France?")]
)
print(response.content.first?.text ?? "")let stream = try await client.messages.stream(
model: .sonnet4_5,
maxTokens: 1024,
messages: [.user("Write a short story")]
)
for try await chunk in stream {
if case .contentBlockDelta(let delta) = chunk,
case .textDelta(let textDelta) = delta.delta {
print(textDelta.text, terminator: "")
}
}let response = try await client.messages.create(
model: .sonnet4_5,
maxTokens: 1024,
messages: [
.user([
.image(source: .base64(mediaType: "image/jpeg", data: base64Image)),
.text("What is in this image?")
])
]
)let tools = [
Tool(
name: "get_weather",
description: "Get current weather for a location",
inputSchema: [
"type": AnyCodable("object"),
"properties": AnyCodable([
"location": ["type": "string", "description": "City name"]
] as [String: Any]),
"required": AnyCodable(["location"])
]
)
]
let response = try await client.messages.create(
model: .sonnet4_5,
maxTokens: 1024,
messages: [.user("What's the weather in Paris?")],
tools: tools
)// Persistent conversations with SwiftData
let sessionManager = try SessionManager()
let sessionID = try await sessionManager.createSession(
title: "Dev Chat",
systemPrompt: "You are an expert Swift developer"
)
// Automatic context window management
let contextManager = ContextManager(maxTokens: 200_000, model: .sonnet4_5)
let trimmed = await contextManager.trimIfNeeded(messages, strategy: .oldest)// Environment variables
let client = ClaudeClient(
credentialProvider: EnvironmentCredentialProvider(key: "ANTHROPIC_API_KEY")
)
// Keychain (production)
let client = ClaudeClient(
credentialProvider: KeychainCredentialProvider(service: "com.myapp.claude")
)The first and only Swift agent framework. Built on the SDK, not alongside it.
AgentKit's core is the AgentLoop — a plan-act-observe-iterate engine:
- Send messages + tools to Claude via
client.messages.create() - If
stopReason == "tool_use"— execute the requested tools - Feed tool results back as a user message
- Repeat until the model returns
end_turnor a stop condition is met
That's it. Everything else — ReAct agents, supervisors, multi-agent teams — is built on this loop.
import AgentKit
let agent = ReActAgent(
client: client,
tools: [
ClosureTool(
name: "search",
description: "Search the web",
inputSchema: Schema.object(
properties: ["query": Schema.string(description: "Search query")],
required: ["query"]
),
handler: { input in
let query = input["query"]?.value as? String ?? ""
return .success(performSearch(query))
}
)
]
)
let result = try await agent.run("Find the latest Swift 6 features")
print(result.output)
print("Iterations: \(result.iterations), Tokens: \(result.totalTokens)")Pre-wired with file system, shell, and code execution tools. Point it at a directory and let it work.
let codeAgent = CodeAgent(
client: client,
workingDirectory: "/path/to/project"
)
let result = try await codeAgent.run("Find the failing test, read the code, fix the bug, and verify the build passes")Creates a numbered plan, works through each step, verifies, and summarizes.
let agent = PlanAndExecuteAgent(
client: client,
tools: [FileSystemTool(basePath: "."), ShellTool()]
)
let result = try await agent.run("Refactor the networking layer to use async/await")Every agent streams events as it works:
let (stream, continuation) = AsyncStream<AgentEvent>.makeStream()
Task {
for await event in stream {
switch event {
case .thinking(let text, let iteration):
print("[\(iteration)] Thinking: \(text.prefix(80))...")
case .toolCallStarted(let name, _, _):
print("Calling \(name)...")
case .toolCallCompleted(let name, _, let duration, _):
print("\(name) completed in \(String(format: "%.1f", duration))s")
case .completed(let result):
print("Done: \(result.output)")
default: break
}
}
}
let result = try await agent.run("Fix the build", events: continuation)Three ways to define tools, from quick to structured:
// 1. Closure — fast and inline
let tool = ClosureTool(
name: "timestamp",
description: "Get the current timestamp",
inputSchema: Schema.object(properties: [:]),
handler: { _ in .success(Date().ISO8601Format()) }
)
// 2. Protocol — for complex tools with state
struct DatabaseTool: AgentTool {
let name = "query_db"
let description = "Run a SQL query"
let inputSchema = Schema.object(
properties: ["sql": Schema.string(description: "SQL query")],
required: ["sql"]
)
func execute(input: [String: AnyCodable]) async throws -> ToolCallResult {
let sql = input["sql"]?.value as? String ?? ""
let rows = try await db.execute(sql)
return .success(rows.description)
}
}
// 3. Result builder — compose tool lists
let agent = ReActAgent(client: client) {
FileSystemTool(basePath: ".")
ShellTool(allowedCommands: ["swift", "git", "ls"])
DatabaseTool()
}Control when agents stop:
let config = AgentConfiguration(
model: .opus4_6,
maxIterations: 50,
stopConditions: [
.endTurn, // Model says it's done
.maxIterations, // Safety limit
.maxTokens(100_000), // Budget limit
.containsText("TASK COMPLETE"), // Keyword trigger
.custom { response, iteration in // Arbitrary logic
iteration > 10 && response.usage.totalTokens > 50_000
}
]
)let team = AgentTeam(name: "dev-team", agents: [
CodeAgent(name: "backend", client: client, workingDirectory: "./backend"),
CodeAgent(name: "frontend", client: client, workingDirectory: "./frontend"),
])
// Run all agents in parallel on the same task
let results = try await team.runAll(input: "Add input validation")
// Or chain them in a pipeline
let result = try await team.pipeline(
input: "Design an API for user profiles",
agentOrder: ["backend", "frontend"]
)let supervisor = Supervisor(
client: client,
agents: [researchAgent, codeAgent, reviewAgent],
model: .opus4_6
)
let result = try await supervisor.run(
task: "Research best practices for Swift concurrency, implement them in our networking layer, then review the changes"
)let handoffTool = HandoffTool(
availableAgents: ["researcher", "coder", "reviewer"],
onHandoff: { targetAgent, context in
// Route to the right agent
}
)Vector search and retrieval-augmented generation, built in.
import MemoryKit
let store = VectorStore()
try await store.add(text: "Swift actors provide data-race safety", tags: ["swift"])
let results = try await store.search("concurrency safety", limit: 5)
// Full RAG pipeline
let pipeline = RAGPipeline(client: client, store: store)
try await pipeline.addKnowledge(text: "SwiftUI uses declarative syntax", tags: ["ui"])
let answer = try await pipeline.query("How does SwiftUI work?")
// Knowledge base with categories
let kb = KnowledgeBase(store: store)
try await kb.addDocument("Swift was introduced in 2014", category: "history")
let facts = try await kb.findRelevant("When was Swift created?", limit: 3)Connect long-term memory to agents:
let bridge = AgentMemoryBridge(knowledgeBase: kb)
// Store agent results as knowledge
try await bridge.storeResult(result, category: "completed_tasks")
// Retrieve relevant context for new tasks
let context = try await bridge.retrieveContext(for: "Fix the auth bug")
// Build enhanced prompts with memory
let prompt = try await bridge.enhancedSystemPrompt(
base: "You are a coding agent.",
query: "Implement OAuth"
)Drop-in views for agent-powered apps. Works with any Agent conforming type.
import AgentKitUI
struct ContentView: View {
let agent = ReActAgent(client: client, tools: myTools)
var body: some View {
AgentChatView(agent: agent)
}
}Full chat interface with message bubbles, input bar, send/stop buttons, and a collapsible tool activity panel. One line.
@State var viewModel = AgentViewModel()
var body: some View {
VStack {
AgentActivityView(viewModel: viewModel)
Button("Run") {
viewModel.run(agent: agent, input: "Fix the build")
}
}
}Live event timeline showing thinking steps, tool calls with durations, iteration counts, and token usage.
ToolCallListView(toolCalls: viewModel.toolCalls)Expandable cards showing each tool's name, input parameters, output, duration, and iteration number.
@State var vm = AgentViewModel()
// vm.isRunning — bool
// vm.currentIteration — int
// vm.output — latest text
// vm.toolCalls — [ToolCallRecord]
// vm.totalTokens — int
// vm.error — AgentError?
// vm.result — AgentResult?
vm.run(agent: myAgent, input: "Do the thing")
vm.cancel()@Observable, so every property change drives SwiftUI updates automatically.
ClaudeSwift (SDK)
Messages API, Streaming, Vision, Tools, Sessions, Context Management
|
MemoryKit
VectorStore, RAGPipeline, KnowledgeBase
|
AgentKit
AgentLoop, AgentTool, ToolRegistry
ReActAgent, PlanAndExecuteAgent, CodeAgent
AgentTeam, Supervisor, Handoff
WorkingMemory, AgentMemoryBridge, AgentSnapshot
|
AgentKitUI
AgentViewModel, AgentChatView, AgentActivityView, ToolCallView
Everything is an actor. Everything is Sendable. Zero external dependencies. Pure Swift.
.opus4_6 // claude-opus-4-6 (most capable)
.sonnet4_5 // claude-sonnet-4-5-20250929 (balanced)
.haiku4_5 // claude-haiku-4-5-20251001 (fastest)
.custom("claude-model-id") // Any model identifier| Requirement | Minimum |
|---|---|
| Swift | 6.0+ |
| iOS | 16.0+ (UI: 17.0+) |
| macOS | 13.0+ (UI: 14.0+) |
| watchOS | 9.0+ (UI: 10.0+) |
| tvOS | 16.0+ (UI: 17.0+) |
| visionOS | 1.0+ |
Contributions welcome. See CONTRIBUTING.md for guidelines.
MIT License. See LICENSE for details.
- Bug reports: GitHub Issues
- Feature requests: GitHub Issues
- Security: security@claudeswift.org
ClaudeSwift is not affiliated with Anthropic PBC. Claude and Anthropic are trademarks of Anthropic PBC.
