展示 HN:我为 Swift 构建了 LangGraph
Show HN: I Built LangGraph for Swift

原始链接: https://github.com/christopherkarani/Swarm

**Swarm** 是一个强大的 Swift 框架,专为构建类型安全、稳健且高性能的 AI 智能体工作流而设计。它基于 **Swift 6.2** 和原生并发机制构建,提供了一种严格类型化且编译为 DAG(有向无环图)的执行模型,确保了复杂智能体交互过程中的安全性。 **主要功能包括:** * **类型安全工具:** `@Tool` 宏可在编译时生成 JSON 模式,确保模型与 Swift 代码之间的无缝交互。 * **持久化工作流:** 通过显式检查点支持故障恢复,允许长时间运行的任务确定性地恢复执行。 * **灵活的执行方式:** 通过顺序、并行、路由以及循环(repeat-until)逻辑来编排工作流。 * **统一抽象:** 插件化架构支持广泛的提供商(OpenAI、Anthropic、Ollama、MLX、基础模型),并使用统一的 API。 * **强大的生产级工具:** 内置内存管理、输入/输出护栏、弹性策略(重试/断路器)以及全面的可观测性。 * **开发者体验:** 具备经过 CI 测试的能力矩阵、通过 `AsyncThrowingStream` 实现的原生流式传输,以及对 MCP(模型上下文协议)的一流支持。 Swarm 专为 iOS、macOS 和 Linux 设计,将企业级的智能体编排引入 Swift 生态系统,专注于编译时安全性和对开发者友好的语法。

```Hacker News最新 | 过往 | 评论 | 提问 | 展示 | 招聘 | 提交登录Show HN: 我为 Swift 构建了 LangGraph (github.com/christopherkarani)7 点,由 christkarani 发布于 2 小时前 | 隐藏 | 过往 | 收藏 | 2 条评论 帮助 sjashwin 49 分钟前 [–] 干得漂亮!回复christkarani 47 分钟前 | 父评论 [–] 谢谢!回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索: ```
相关文章

原文
let result = try await Workflow()
    .step(researchAgent)
    .step(writerAgent)
    .run("Summarize the latest WWDC session on Swift concurrency.")

Two agents, one pipeline, compiled to a DAG with crash recovery and Swift concurrency safety.

.package(url: "https://github.com/christopherkarani/Swarm.git", from: "0.6.0")
import Swarm

// The @Tool macro generates the JSON schema at compile time
@Tool("Looks up the current stock price")
struct PriceTool {
    @Parameter("Ticker symbol") var ticker: String
    func execute() async throws -> String { "182.50" }
}

// Create an agent with unlabeled instructions first and tools in the trailing @ToolBuilder closure
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."

That is a working agent with type-safe tool calling. Swarm also supports AGENTS.md and SKILL.md for declarative agent specs and reusable skills — see the Getting Started guide for the full workspace layout.

  • Swift concurrency is part of the surface. Swift 6.2 StrictConcurrency is enabled across the package.
  • Tools stay type-safe. The @Tool macro generates JSON schemas from Swift structs.
  • Workflows can survive crashes. Durable workflow checkpointing lets you resume from an explicit checkpoint ID.
  • Cloud and on-device models use the same abstractions. Foundation Models, Anthropic, OpenAI, Ollama, Gemini, MiniMax, OpenRouter, and MLX all fit the same shape.
  • It is written in Swift all the way down. AsyncThrowingStream, actors, result builders, and macros are first-class here.

Capability matrix showcase

Swarm now ships with an in-repo capability showcase that exercises the stable surface area in one deterministic matrix:

  • agents and tools
  • streaming
  • conversation plus session persistence
  • sequential, parallel, routed, and repeat-until workflows
  • handoffs
  • memory
  • on-device workspace loading
  • guardrails
  • resilience helpers
  • durable checkpoint and resume
  • observability
  • MCP discovery and tool bridging
  • provider selection

Run it locally:

swift run SwarmCapabilityShowcase list
swift run SwarmCapabilityShowcase matrix
swift run SwarmCapabilityShowcase run handoff
swift run SwarmCapabilityShowcase smoke

The deterministic matrix is CI-safe. Live-provider smoke coverage is opt-in through environment variables. See docs/guide/capability-showcase.md for the scenario catalog and smoke-mode details.

Demo executables are opt-in so the default library graph stays focused on the framework products:

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")

Each agent resolves its own provider. Pass inferenceProvider: per agent (as above), or call await Swarm.configure(provider: .anthropic(apiKey: "...")) once at app startup to share a default across every agent that doesn't specify one.

let result = try await Workflow()
    .parallel([bullAgent, bearAgent, analystAgent], merge: .structured)
    .run("Evaluate Apple's Q4 earnings.")
// Three perspectives, merged into one output.
let result = try await Workflow()
    .route { input in
        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 // Other events include .output(.thinking(...)), .handoff(...), .observation(...), and .lifecycle(.iterationStarted(...)).
    }
}
More examples
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])

Crash-resumable workflows

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")
// On-device, private, no API key needed
let local = try Agent("Be helpful.", inferenceProvider: .foundationModels())

// Cloud
let cloud = try Agent("Be helpful.", inferenceProvider: .anthropic(key: k))

// Or swap at runtime via environment
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?") // Context preserved

for message in await conversation.messages {
    print("\(message.role): \(message.text)")
}
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       │
├─────────────────────────────────────────────────────────────┤
│  InputGuard · OutputGuard · Resilience · Observability · MCP│
├─────────────────────────────────────────────────────────────┤
│              Durable Graph Runtime (internal)               │
│   Workflow Graph  ·  Checkpointing  ·  Deterministic retry │
├─────────────────────────────────────────────────────────────┤
│              InferenceProvider (pluggable)                   │
│ Foundation Models · Anthropic · OpenAI · Ollama · OpenRouter│
└─────────────────────────────────────────────────────────────┘
Platform Minimum
Swift 6.2+
iOS 26.0+
macOS 26.0+
tvOS 26.0+
Linux Ubuntu 22.04+ with Swift 6.2

The default Swarm graph is CI-tested on Ubuntu with Swift 6.2. Apple-only features such as Foundation Models, SwiftData, OSLog, and some built-in tool behavior are unavailable or different on Linux; cloud providers and Ollama use the shared InferenceProvider surface.

  1. Fork → branch → swift test → PR
  2. All public types must be Sendable; the compiler enforces it
  3. Format with swiftformat Sources Tests --lint --config .swiftformat

Bug reports and feature requests: GitHub Issues

GitHub Issues · Discussions · @ckarani7

If Swarm saves you time, a star helps others find it.

Released under the MIT License.

联系我们 contact @ memedata.com