Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 19 additions & 35 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import PackageDescription
import CompilerPluginSupport
import Foundation

let includeDemo = ProcessInfo.processInfo.environment["SWARM_INCLUDE_DEMO"] == "1"

let packageRoot = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
let useLocalDependencies = ProcessInfo.processInfo.environment["SWARM_USE_LOCAL_DEPS"] == "1"
let includeDemo = ProcessInfo.processInfo.environment["SWARM_INCLUDE_DEMO"] == "1"
let useLocalDeps = ProcessInfo.processInfo.environment["AISTACK_USE_LOCAL_DEPS"] == "1"

var packageProducts: [Product] = [
.library(name: "Swarm", targets: ["Swarm"]),
Expand All @@ -23,36 +22,26 @@ if includeDemo {
var packageDependencies: [Package.Dependency] = [
.package(url: "https://github.com/swiftlang/swift-syntax.git", "600.0.0"..<"603.0.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
.package(url: "https://github.com/modelcontextprotocol/swift-sdk.git", from: "0.10.0")
.package(url: "https://github.com/modelcontextprotocol/swift-sdk.git", from: "0.10.0"),
]

if useLocalDependencies {
// NOTE: Local development override.
let waxCandidates = ["../Wax", "../rag/Wax"]
let waxPath = waxCandidates.first(where: { candidate in
FileManager.default.fileExists(atPath: packageRoot.appendingPathComponent(candidate).path)
}) ?? "../Wax"

packageDependencies.append(.package(path: waxPath))
packageDependencies.append(
if useLocalDeps {
packageDependencies += [
.package(path: packageRoot.appendingPathComponent("../Wax").path),
.package(
path: "../Conduit",
path: packageRoot.appendingPathComponent("../Conduit").path,
traits: [
.trait(name: "OpenAI"),
.trait(name: "OpenRouter"),
.trait(name: "Anthropic"),
]
)
)
packageDependencies.append(.package(path: "../Membrane"))
),
.package(path: packageRoot.appendingPathComponent("../Membrane").path),
.package(path: packageRoot.appendingPathComponent("../Hive").path),
]
} else {
packageDependencies.append(
.package(
url: "https://github.com/christopherkarani/Wax.git",
from: "0.1.3"
)
)
packageDependencies.append(
packageDependencies += [
.package(url: "https://github.com/christopherkarani/Wax.git", from: "0.1.17"),
.package(
url: "https://github.com/christopherkarani/Conduit",
exact: "0.3.5",
Expand All @@ -61,23 +50,17 @@ if useLocalDependencies {
.trait(name: "OpenRouter"),
.trait(name: "Anthropic"),
]
)
)
packageDependencies.append(
.package(
url: "https://github.com/christopherkarani/Membrane",
.branch("main")
)
)
),
.package(url: "https://github.com/christopherkarani/Membrane", from: "0.1.1"),
.package(url: "https://github.com/christopherkarani/Hive", from: "0.1.7"),
]
}

packageDependencies.append(.package(url: "https://github.com/christopherkarani/Hive", from: "0.1.0"))

var swarmDependencies: [Target.Dependency] = [
"SwarmMacros",
.product(name: "Logging", package: "swift-log"),
.product(name: "Conduit", package: "Conduit"),
.product(name: "Wax", package: "Wax"),
.product(name: "ConduitAdvanced", package: "Conduit"),
.product(name: "HiveCore", package: "Hive"),
.product(name: "Membrane", package: "Membrane", condition: .when(traits: ["membrane"])),
.product(name: "MembraneHive", package: "Membrane", condition: .when(traits: ["membrane"]))
Expand Down Expand Up @@ -146,6 +129,7 @@ var packageTargets: [Target] = [
"Swarm",
"SwarmHive",
"SwarmMCP",
.product(name: "ConduitAdvanced", package: "Conduit"),
],
resources: [
.copy("Guardrails/INTEGRATION_TEST_SUMMARY.md"),
Expand Down
40 changes: 27 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ struct PriceTool {
func execute() async throws -> String { "182.50" }
}

// Create an agent — instructions first, tools in trailing closure
// Create an agent — unlabeled instructions first, tools in @ToolBuilder trailing closure
let agent = try Agent("Answer finance questions using real data.",
configuration: .default.name("Analyst"),
configuration: .init(name: "Analyst"),
inferenceProvider: .anthropic(key: "sk-...")) {
PriceTool()
CalculatorTool()
Expand Down Expand Up @@ -125,7 +125,7 @@ for try await event in agent.stream("Summarize the changelog.") {
```swift
let agent = try Agent("You remember past conversations.",
inferenceProvider: .anthropic(key: "sk-..."),
memory: VectorMemory(embeddingProvider: myEmbedder, threshold: 0.75)) {
memory: .vector(embeddingProvider: myEmbedder, threshold: 0.75)) {
// tools
}
```
Expand All @@ -134,8 +134,8 @@ let agent = try Agent("You remember past conversations.",

```swift
let agent = try Agent("You are a helpful assistant.",
inputGuardrails: [MaxLengthGuardrail(limit: 5000), NotEmptyGuardrail()],
outputGuardrails: [MaxLengthGuardrail(limit: 2000)])
inputGuardrails: [GuardrailSpec.maxInput(5000), GuardrailSpec.inputNotEmpty],
outputGuardrails: [GuardrailSpec.maxOutput(2000)])
```

#### Closure tools — no struct needed
Expand Down Expand Up @@ -174,7 +174,20 @@ let local = try Agent("Be helpful.", inferenceProvider: .foundationModels)
let cloud = try Agent("Be helpful.", inferenceProvider: .anthropic(key: k))

// Or swap at runtime via environment
let modified = agent.environment(\.inferenceProvider, .ollama("mistral"))
let modified = agent.environment(\.inferenceProvider, .ollama(model: "mistral"))
```

#### Conversation — stateful multi-turn

```swift
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)")
}
```

</details>
Expand All @@ -199,8 +212,9 @@ let modified = agent.environment(\.inferenceProvider, .ollama("mistral"))
| **Agents** | `Agent` struct with `@ToolBuilder` trailing closure, `AgentRuntime` protocol |
| **Workflows** | `Workflow`: `.step()`, `.parallel()`, `.route()`, `.repeatUntil()`, `.timeout()` |
| **Tools** | `@Tool` macro, `FunctionTool`, `@ToolBuilder`, parallel execution |
| **Memory** | `ConversationMemory`, `VectorMemory`, `SlidingWindowMemory`, `SummaryMemory` |
| **Guardrails** | `InputGuardrail`, `OutputGuardrail`, `ToolInputGuardrail`, `ToolOutputGuardrail` |
| **Memory** | `MemoryOption.conversation(limit:)`, `MemoryOption.vector(embeddingProvider:)`, `MemoryOption.slidingWindow(count:)`, `MemoryOption.summary(summarizer:)` |
| **Guardrails** | `GuardrailSpec.maxInput()`, `GuardrailSpec.maxOutput()`, `GuardrailSpec.inputNotEmpty`, `GuardrailSpec.outputNotEmpty`, `GuardrailSpec.customInput()`, `GuardrailSpec.customOutput()` |
| **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 |
Expand All @@ -214,14 +228,14 @@ let modified = agent.environment(\.inferenceProvider, .ollama("mistral"))
│ Your Application │
│ iOS 26+ · macOS 26+ · Linux (Ubuntu 22.04+) │
├─────────────────────────────────────────────────────────────┤
│ Workflow · .run() · .stream()
│ Workflow · Conversation · .run() · .stream() │
├─────────────────────────────────────────────────────────────┤
│ Agents Memory Tools │
│ Agent (struct) ConversationMemory @Tool macro │
│ AgentRuntime VectorMemory FunctionTool
SummaryMemory @ToolBuilder │
│ Agent (struct) MemoryOption @Tool macro │
│ AgentRuntime Conversation FunctionTool │
(dot-syntax) @ToolBuilder │
├─────────────────────────────────────────────────────────────┤
Guardrails · Resilience · Observability · MCP
GuardrailSpec · Resilience · Observability · MCP │
├─────────────────────────────────────────────────────────────┤
│ Hive Runtime (optional) │
│ Compiled DAG · Checkpointing · Deterministic retry │
Expand Down
Loading