HN 日本語サマリー

← 一覧へ戻る
AI・機械学習

Show HN: SwiftでLangGraphを構築しました

Show HN: I Built LangGraph for Swift (github.com)

16 pointsby christkarani3 コメント

要約

Swarmは、Swiftでエージェントとマルチエージェントワークフローを構築するためのフレームワークです。Swiftのコンカレンシー安全性を活用し、コンパイル時の型安全なツール呼び出し、クラッシュからの復旧、多様な基盤モデルとの連携を可能にします。宣言的なエージェント仕様やスキル定義もサポートしており、iOS/macOS開発者にとってAIエージェント構築の強力な選択肢となります。

全文翻訳

Swiftでエージェントとマルチエージェントワークフローを構築するためのフレームワークです。 let result = try await Workflow() .step(researchAgent) .step(writerAgent) .run("Summarize the latest WWDC session on Swift concurrency.") 2つのエージェント、1つのパイプライン、クラッシュリカバリとSwiftコンカレンシー安全性を備えたDAGにコンパイルされます。 .package(url: "https://github.com/christopherkarani/Swarm.git", from: "0.6.0") をインストールします。 クイックスタート import Swarm // @Tool マクロはコンパイル時にJSONスキーマを生成します @Tool("Looks up the current stock price") struct PriceTool { @Parameter("Ticker symbol") var ticker: String func execute() async throws -> String { "182.50" } } // ラベルなしの指示でエージェントを作成し、後続の @ToolBuilder クロージャでツールを使用します let agent = try Agent("Answer finance questions using real data.", configuration: .init(name: "Analyst"), inferenceProvider: .anthropic(key: "{ENV}")) { PriceTool() CalculatorTool() } let result = try await agent.run("What is AAPL trading at?") print(result.output) // "Apple (AAPL) is currently trading at $182.50." これは動作するエージェントで、型安全なツール呼び出しが可能です。 Swarmは宣言的なエージェント仕様と再利用可能なスキル用のAGENTS.mdおよびSKILL.mdもサポートしています。完全なワークスペースレイアウトについては、Getting Startedガイドを参照してください。 Swarmを選ぶ理由 Swiftコンカレンシーは表面の一部です。Swift 6.2 StrictConcurrencyがパッケージ全体で有効になっています。 ツールは型安全性を保ちます。 @Tool マクロはSwift構造体からJSONスキーマを生成します。 ワークフローはクラッシュから回復できます。 永続的なワークフローチェックポインティングにより、明示的なチェックポイントIDから再開できます。 クラウドおよびオンデバイスモデルは同じ抽象化を使用します。 Foundation Models, Anthropic, OpenAI, Ollama, Gemini, MiniMax, OpenRouter, MLXはすべて同じ形状に適合します。 すべてSwiftで書かれています。 AsyncThrowingStream, アクター, 結果ビルダー, マクロはここでファーストクラスです。 例 機能マトリックスはSwarmに、1つの決定論的なマトリックスで安定したサーフェスエリアを行使するインリポジトリの機能ショーケースを現在出荷しています。 エージェントとツール 会話のストリーミングとセッションの永続化 シーケンシャル、パラレル、ルーティング、リピートアンティルワークフロー ハンドオフ メモリ オンデバイスワークスペースのロード ガードレール レジリエンスヘルパー 永続的なチェックポイントと再開 オブザーバビリティ MCPディスカバリとツールブリッジング プロバイダー選択 ローカルで実行: swift run SwarmCapabilityShowcase list swift run SwarmCapabilityShowcase matrix swift run SwarmCapabilityShowcase run handoff swift run SwarmCapabilityShowcase smoke 決定論的なマトリックスはCIセーフです。ライブプロバイダーのスモークカバレッジは、環境変数を通じてオプトインです。シナリオカタログとスモークモードの詳細については、docs/guide/capability-showcase.mdを参照してください。 オプションデモ デモ実行可能ファイルはオプトインなので、デフォルトのライブラリグラフはフレームワーク製品に焦点を当てています。 SWARM_INCLUDE_DEMO=1 swift build SWARM_INCLUDE_DEMO=1 swift run SwarmDemo SWARM_INCLUDE_DEMO=1 swift run SwarmMCPServerDemo マルチエージェントパイプライン let researcher = try Agent("Research the topic and extract key facts.", inferenceProvider: .anthropic(key: "sk-...")) { WebSearchTool() } let writer = try Agent("Write a concise summary from the research.", inferenceProvider: .anthropic(key: "sk-...")) let result = try await Workflow() .step(researcher) .step(writer) .run("Latest advances in on-device ML") 各エージェントは独自のプロバイダーを解決します。 inferenceProvider: をエージェントごとに渡す(上記参照)、またはアプリ起動時に一度 await Swarm.configure(provider: .anthropic(apiKey: "...")) を呼び出して、指定されていないすべてのエージェントでデフォルトを共有します。 パラレルファンアウト let result = try await Workflow() .parallel([bullAgent, bearAgent, analystAgent], merge: .structured) .run("Evaluate Apple's Q4 earnings.") // 3つの視点が1つの出力にマージされます。 ダイナミックルーティング let result = try await Workflow() .route { if input.contains("$") { return mathAgent } if input.contains("weather") { return weatherAgent } return generalAgent } .run("What is 15% of $240?") ストリーミング for try await event in agent.stream("Summarize the changelog.") { switch event { case .output(.token(let t)): print(t, terminator: "") case .tool(.completed(let call, _)): print("\n[tool: \(call.toolName)]") case .lifecycle(.completed(let r)): print("\nDone in \(r.duration)") case .lifecycle(.failed(let error)): print("\nError: \(error)") default: break // 他のイベントには .output(.thinking(...)), .handoff(...), .observation(...), .lifecycle(.iterationStarted(...)) が含まれます。 } } その他の例 セマンティックメモリ let agent = try Agent("You remember past conversations.", inferenceProvider: .anthropic(key: "sk-..."), memory: .vector(embeddingProvider: myEmbedder, similarityThreshold: 0.75)) { // tools } ガードレール let agent = try Agent("You are a helpful assistant.", inputGuardrails: [InputGuard.maxLength(5000), InputGuard.notEmpty()], outputGuardrails: [OutputGuard.maxLength(2000)]) クロージャツール let reverse = FunctionTool( name: "reverse", description: "Reverses a string", parameters: [ ToolParameter(name: "text", description: "Text to reverse", type: .string, isRequired: true) ] ) { args in let text = try args.require("text", as: String.self) return .string(String(text.reversed())) } let agent = try Agent("Text utilities.", tools: [reverse]) クラッシュ耐性のあるワークフロー let workflow = Workflow() .step(monitor) .durable.checkpoint(id: "monitor-v1", policy: .everyStep) .durable.checkpointing(.fileSystem(directory: checkpointsURL)) let resumed = try await workflow.durable.execute("watch", resumeFrom: "monitor-v1") プロバイダーの切り替え // オンデバイス、プライベート、APIキー不要 let local = try Agent("Be helpful.", inferenceProvider: .foundationModels()) // クラウド let cloud = try Agent("Be helpful.", inferenceProvider: .anthropic(key: k)) // または環境変数経由で実行時に切り替え let modified = agent.environment(\.inferenceProvider, .ollama(model: "mistral")) 会話 let conversation = Conversation(with: agent) let response1 = try await conversation.send("What's the weather?") let response2 = try await conversation.send("And tomorrow?") // コンテキストはメッセージの保持に役立ちます for message in await conversation.messages { print("\(message.role): \(message.text)") } Swarmと他フレームワークの比較 Swarm | LangChain | AutoGen ---|---|--- Language | Swift 6.2 | Python | Python Data race safety | Compile-time | Runtime | Runtime On-device LLM | Foundation Models | n/a | n/a Execution model | Typed Workflow graph | Loop-based | Loop-based Crash recovery | Checkpoints | n/a | Partial Type-safe tools | @Tool macro (compile-time) | Decorators (runtime) | Runtime Streaming | AsyncThrowingStream | Callbacks | Callbacks iOS / macOS native | First-class | n/a | n/a 含まれるもの Agents | Agent struct with @ToolBuilder trailing closure, AgentRuntime protocol Workflows | Workflow: .step(), .parallel(), .route(), .repeatUntil(), .timeout() Tools | @Tool macro, FunctionTool, @ToolBuilder, parallel execution Memory | .conversation(maxMessages:), .vector(embeddingProvider:similarityThreshold:maxResults:), .slidingWindow(maxTokens:), .summary(configuration:summarizer:), .hybrid(configuration:summarizer:) Guardrails | InputGuard.maxLength(), InputGuard.notEmpty(), InputGuard.custom(), OutputGuard.maxLength(), OutputGuard.custom() Conversation | Conversation actor for stateful multi-turn dialogue Resilience | 7 backoff strategies, circuit breaker, fallback chains, rate limiting Observability | AgentObserver, Tracer, SwiftLogTracer, per-agent token metrics MCP | Model Context Protocol client and server support Providers | Foundation Models, Anthropic, OpenAI, Ollama, Gemini, MiniMax, OpenRouter, MLX via Conduit Macros | @Tool, @Parameter, @Traceable, #Prompt アーキテクチャ ┌─────────────────────────────────────────────────────────────┐ │ Your Application │ │ iOS 26+ · macOS 26+ · Linux (Ubuntu 22.04+) │ ├─────────────────────────────────────────────────────────────┤ │ Workflow · Conversation · .run() · .stream() │ ├─────────────────────────────────────────────────────────────┤ │ Agents Memory Tools │ │ Agent (struct) Memory factories @Tool macro │ │ AgentRuntime Conversation FunctionTool │ │ (dot-syntax) @ToolBuilder │ ├─────────────────────