Açık Kaynak Pazartesi'si: ClaudeSwiftSDK ve AgentKit
Swift programlama dilini günlük hayatımda neredeyse birçok programlama ihtiyacımı çözmek için kullanıyorum diyebilirim. Bunun en büyük sebeplerinden birisi Swift'in type-safe olması. Bunun yanı sıra Swift'in açık kaynak olması ve arkasında çok güçlü bir ekosistemin olması da beni Swift ekosisteminde bir geliştirici olarak çok kabiliyetli hissettiriyor. Swift'in geliştirici forumlarında yorumlanan, tartışılan ve şekillendirilen kararlar, bu dilin sadece Apple'ın değil, tüm topluluğun eseri olduğunu açıkça ortaya koyuyor diye düşünüyorum.
Bu ekosistemde teknik içeriklere göz atmaya başladığınızda fark edeceğiniz ilk şey, tüketilecek çok fazla teknik içeriğin olması. Forum tartışmaları, evolution proposal'ları, WWDC session'ları, açık kaynak paketler, YouTube konuşmaları, blog yazıları, tüm bunların hepsini üst üste eklediğinizde, bir mühendis olarak kendinizi sürekli bir öğrenme döngüsünün içinde buluyorsunuz. Ve bu sürecin en güzel tarafı, bu döngü sizi daha iyi bir Swift geliştiricisi yapmakla kalmıyor, programlama dili tasarımı, concurrency modelleri ve yazılım mimarisi konularında da derinleştiriyor. Bir forum thread'ini okumaya başlıyorsunuz, sonra kendinizi bir Swift Evolution proposal'ının GitHub diff'ini incelerken buluyorsunuz, oradan da bir FOSDEM konuşmasına geçiyorsunuz ve farkında olmadan saatler geçmiş oluyor.
Swift.org'un Şubat 2026 bülteninde yer alan Swift Barcelona konuşması ve Xcode 26.3'ün agentic coding desteği, Swift'in artık salt iOS uygulama geliştirme paradigmasının ötesine geçtiğini de ortaya koyuyor. Bu yazıda da iki açık kaynak paketinden bahsetmek istiyorum, birisi Swift bülteninde yer alan SwiftAI paketi ve diğeri de bu hafta geliştirdiğim ClaudeSwiftSDK. İkisi de Swift'te AI uygulamaları geliştirmek için tasarlandı, ancak farklı soruları cevaplıyorlar. SwiftAI bir API client'ı olarak LLM entegrasyonunu kolaylaştırırken, ClaudeSwiftSDK tam bir agent framework sunuyor. Bu iki paketin ne yaptığını, nasıl çalıştığını ve aralarındaki farkı somut kod örnekleriyle anlatmaya çalışacağım.
SwiftAI: LLM Entegrasyonu için Deklaratif Araçlar
SwiftAI, birden fazla LLM provider'ını tek bir arayüzde birleştiren bir Swift paketi. Benim için en dikkat çekici tarafı, Swift macro'larını kullanarak tool tanımlamayı temiz hale getirmesi.
@Tool Macro'su ile Araç Tanımlama
SE-0389 ile Swift'e eklenen macro sistemi burada aslında pratik olarak karşılığını buluyor. JSON schema'ları elle yazmak yerine Swift struct'ları yazıyorsunuz:
import AITool
@Tool
struct RunSwiftCode {
static let name = "run_swift_code"
static let description = "Compiles and runs a Swift code snippet."
@Parameter(description: "The Swift code to execute")
var code: String
func perform() async throws -> String {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
process.arguments = ["swift", "-e", code]
// ... process çalıştır, stdout/stderr döndür
}
}
@Tool macro'su compile-time'da bu struct'ı analiz edip gerekli JSON schema'yı, parametre doğrulamasını ve tool dispatch mekanizmasını otomatik oluşturuyor.
Streaming ve Agentic Loop
SwiftAI'ın streamText metodu bir AsyncThrowingStream<GenerationResponse, Error> döndürüyor. Her yield edilen response'un texts.response alanı o ana kadar biriken tam metni içeriyor. Bu sayede SwiftUI'da tek bir assignment ile UI güncelleniyor:
let stream = client.streamText(
modelId: "claude-haiku-4-5-20251001",
tools: DemoTools.all,
systemPrompt: "You are a helpful assistant with access to tools.",
messages: apiMessages,
maxTokens: 4096,
apiKey: apiKey
)
for try await response in stream {
if let text = response.texts.response {
messages[assistantIndex].text = text
}
}
Yani Claude bir araç çağırmak istediğinde, o aracı çalıştırıp sonucu tekrar Claude'a gönderiyorsunuz. Claude sonucu görüyor, gerekiyorsa başka bir araç çağırıyor veya nihai yanıtını veriyor:
while iteration < maxIterations {
// ... response'u stream et ...
if finalResponse.toolCalls.isEmpty { break }
apiMessages.append(finalResponse.message)
let results = await tools.call(finalResponse.toolCalls)
apiMessages.append(results.message)
}
Bu döngü, uygulama ile Claude arasında süregelen bir diyalog gibi çalışıyor. apiMessages array'i bu diyaloğun tüm geçmişini kronolojik sırayla tutuyor, çünkü Claude'un her yeni istekte önceki konuşmanın tamamını görmesi gerekiyor. SwiftAI bu akışı mümkün kılıyor, ancak agentic loop'un kendisini ise biz elle yazıyoruz.
ClaudeSwiftSDK: Yeni Swift Agent Framework'ü
SwiftAI'ın demo uygulamasını izlerken fark ettiğim bir nokta oldu: while döngüsü, toolCalls.isEmpty kontrolü, apiMessages.append, bunların hepsi geliştiricinin sorumluluğundaydı. Böyle düşündüğümde, SwiftAI'ın bir API client'ı olarak çok iyi bir araç olduğunu düşünüyorum ama agentic uygulamanın "beynini", yani plan yapma, araç seçme ve hafıza yönetimi gibi üst seviye davranışları geliştiriciye bırakıyor.
Bu boşluğu doldurmak için ClaudeSwiftSDK'yı geliştirdim. Paketin temel motivasyonu benim için Swift üzerinde bir agent framework'ü eksikliğini kapatmaktı. Paketi dört modüler kütüphane olarak tasarladım:
ClaudeSwift (SDK)
→ MemoryKit (RAG)
→ AgentKit (Agent Framework)
→ AgentKitUI (SwiftUI)
ClaudeSwift: API Katmanı
En alt katman olan ClaudeSwift, Anthropic'in Claude API'sini wrap ediyor. Message creation, streaming, vision ve tool use gibi temel özelliklerin hepsini destekliyor. SwiftAI'dan farklı olarak sadece Claude'a odaklanıyor. ClaudeSwift'e SwiftData ile session persistence, Keychain tabanlı credential management, context window yönetimi ve retry policy'ler gibi production-ready özellikler ekledim. Bu özelliklerin yüksek ölçekli production ortamında ihtiyaç duyulan bazı çözümleri sunduğunu düşünüyorum.
MemoryKit: Agent'lara Hafıza Kazandırmak
Bir agent'ın gerçekten işlevsel olabilmesi için bazı durumlarda önceki konuşmalardan öğrendiğini hatırlaması, ilgili bilgiyi bulup getirmesi ve bilgi tabanlarını organize etmesi gerekebiliyor. Hafıza olmadan agent her konuşmaya sıfırdan başlıyor ve bu da tekrarlayan görevlerde verimsizliğe yol açıyor. Ancak hafıza eklemek de trade-off'suz gelmiyor. Embedding hesaplaması ek gecikme getiriyor ve vektör deposu bağlam (context) tüketiyor. Retrieval kalitesi chunk boyutu ile embedding model seçimine doğrudan bağlı olduğu için MemoryKit bu dengeleri göz önünde bulundurarak tasarlandı:
let store = VectorStore()
await store.add("Swift actors thread-safe erişim sağlar", tags: ["concurrency"])
await store.add("SwiftUI @Observable macro ile state yönetimi", tags: ["ui"])
let results = await store.search("thread safety nasıl çalışır?", limit: 3)
Burada önce bir VectorStore oluşturuyoruz ve içine iki farklı bilgi parçasını tag'leriyle birlikte ekliyoruz. Sonra "thread safety nasıl çalışır?" diye bir arama yapıyoruz. Burada dikkat ederseniz arama sorgusu ile eklediğimiz metinler birebir aynı kelimeleri içermiyor, ama VectorStore anlamsal benzerliğe bakarak "Swift actors thread-safe erişim sağlar" metnini en alakalı sonuç olarak döndürüyor. Bu klasik keyword aramasından farklı olarak, metnin anlamını yakalayan bir arama.
VectorStore in-memory embedding tabanlı semantik arama yapıyor. Eklediğiniz metinleri vektör temsillerine dönüştürüyor ve yeni bir sorgu geldiğinde cosine similarity ile en alakalı sonuçları buluyor. RAGPipeline ise bu store'u LLM çağrılarıyla birleştiriyor: önce kullanıcının sorusuna en yakın dökümanları VectorStore'dan çekiyor, sonra bu dökümanları bağlam olarak LLM'e gönderiyor. Böylece model, kendi eğitim verisinde olmayan bilgilere de dayanarak yanıt üretebiliyor. KnowledgeBase ile dökümanları kategorize edip tag'leyebiliyorsunuz, AgentMemoryBridge ise tüm bu hafıza bileşenlerini agent execution'ına bağlıyor. Bu sayede aslında Python'daki LangChain veya LlamaIndex'in sağladığı işlevi burada Swift'te, Swift'in type-safe yapısı içinde yapmış oluyoruz.
AgentKit: Planla, Uygula, Gözlemle
AgentKit, ClaudeSwiftSDK'nın kalbi ve SwiftAI ile arasındaki en büyük farkın ortaya çıktığı yer. SwiftAI'da agentic loop'u elle yazarken, AgentKit bu döngüyü framework'ün içerisinde sağlıyor:
import AgentKit
let agent = ReActAgent(
client: ClaudeClient(credentialProvider: .environment("ANTHROPIC_API_KEY")),
tools: [FileSystemTool(), ShellTool(), CodeExecutionTool()],
configuration: .init(
model: .claude_haiku_4_5,
maxIterations: 10,
systemPrompt: "Sen yardımcı bir Swift geliştirme asistanısın."
)
)
let result = try await agent.run("Projedeki tüm test dosyalarını bul ve test coverage raporunu oluştur")
Bu run çağrısıyla aslında Agent kendi başına hangi araçları kullanacağına karar veriyor, araçları çalıştırıyor, sonuçları değerlendiriyor ve gerekirse tekrar araç çağırıyor. Elle yazdığımız tüm o while döngüsü ve apiMessages.append zinciri AgentLoop tarafından yönetiliyor.
Her görev tipi farklı bir çözüm stratejisi gerektirdiği için AgentKit'te üç farklı agent pattern'i sunuyorum:
- ReActAgent: Her adımda "düşünce, eylem, gözlem" döngüsü
- PlanAndExecuteAgent: Önce plan oluşturuyor, sonra adım adım uyguluyor
- CodeAgent: Dosya sistemi, shell ve kod çalıştırma araçlarıyla önceden donatılmış, yazılım geliştirme görevlerine özel agent
Multi-Agent Orchestration
ClaudeSwiftSDK aracılığıyla birden fazla agent'ı bir araya getirip karmaşık görevleri koordineli bir şekilde çözebilmeniz de mümkün:
let supervisor = Supervisor(
client: client,
agents: [
"researcher": researchAgent,
"coder": codingAgent,
"reviewer": reviewAgent
]
)
let result = try await supervisor.run("Bu bug'ı araştır, düzelt ve code review yap")
Supervisor pattern'inde LLM kendisi orchestrator rolünü üstleniyor ve gelen görevi analiz edip hangi agent'a delege edeceğine karar veriyor.
Real-Time Event Stream
AgentKit'e eklediğim bir başka özellik de AsyncStream tabanlı event sistemi. Agent çalışırken neler olduğunu gerçek zamanlı olarak izleyebiliyorsunuz:
for await event in agent.events {
switch event {
case .thinking(let thought):
print("Düşünüyor: \(thought)")
case .toolCallStarted(let name, _):
print("Araç çağrılıyor: \(name)")
case .toolCallCompleted(let name, let result, let duration):
print("\(name) tamamlandı (\(duration)s)")
case .iterationCompleted(let count, let tokens):
print("İterasyon \(count), \(tokens) token kullanıldı")
default: break
}
}
AgentKitUI: Hazır SwiftUI Bileşenleri
SwiftAI aracını kullanırken UI tarafındaki chat bubble'ları, tool call gösterimi ve loading state'leri gibi bileşenler hazır gelmediği için ClaudeSwiftSDK'ya AgentKitUI modülünü de ekledim:
import AgentKitUI
struct ContentView: View {
@State private var viewModel = AgentViewModel(agent: myAgent)
var body: some View {
VStack {
AgentChatView(viewModel: viewModel)
AgentActivityView(viewModel: viewModel)
}
}
}
AgentChatView tam bir chat arayüzü sunuyor. AgentActivityView agent'ın düşünme sürecini bir timeline olarak gösteriyor ve hepsi @Observable protokolü üzerinden AgentViewModel ile gerçek zamanlı güncelleniyor. Hızlı prototipleme yapmak isteyen geliştiriciler için zaman tasarrufu sağlıyor.
İki Yaklaşım, Bir Ekosistem
SwiftAI ve ClaudeSwiftSDK araçlarının birbirini tamamlayan projeler olduğunu düşünüyorum. İkisi de Swift'in modern özelliklerini, yani async/await, actor, AsyncStream ve @Observable gibi yapıları sonuna kadar kullanıyor. Ama farklı soruları cevaplıyorlar:
SwiftAI "Herhangi bir LLM'i Swift'te nasıl kullanırım?" sorusunu cevaplıyor. Multi-provider desteği, @Tool macro'su ve MCP bridge ile geniş bir yelpaze sunuyor. Hızlı prototipleme veya provider karşılaştırması gereken senaryolarda kullanışlı.
ClaudeSwiftSDK ise "Claude ile Swift'te tam bir agent sistemi nasıl kurarım?" sorusunu cevaplıyor. AgentKit ile hazır agent pattern'leri, MemoryKit ile RAG pipeline ve AgentKitUI ile SwiftUI bileşenleri sunuyor. ClaudeSwiftSDK Claude'a odaklı, derinlemesine bir agent framework olarak düşünülebilir.
Pratikte bir API ile konuşmak istiyorsanız SwiftAI, bir agent sistemi inşa etmek istiyorsanız ClaudeSwiftSDK daha uygun gibi düşünebilirsiniz. İkisinin de arkasında aynı Swift Evolution temelleri var.
Sonuç
Bu iki paketin ortak noktası, Swift'in AI alanında da ciddi bir ekosistem alternatifi olduğunu göstermesi diye düşünüyorum. async/await ile streaming, actor ile thread safety, macro'lar ile deklaratif API tasarımı gibi temeller üzerinde agent framework'leri inşa edilebiliyor.
Artık Swift ile sadece iOS uygulamaları değil, LLM tool integration'dan MCP server'larına, agentic workflow'lardan terminal uygulamalarına kadar geniş bir yelpaze üzerinde çalışabiliyorsunuz. Ve tüm bunlar açık kaynak paketler üzerinden, topluluğun katkısıyla inşa ediliyor.
SwiftAI'ı denemenizi ve ClaudeSwiftSDK'nın kaynak kodunu incelemenizi öneriyorum. Katkıda bulunmak isterseniz ClaudeSwiftSDK'nın GitHub reposunda "Good First Issue" etiketli görevler mevcut.