SwiftAgent

main

A Swift framework that enables declarative development of AI agents with SwiftUI-like syntax, embracing type-safety and composability.
1amageek/SwiftAgent

SwiftAgent

Ask DeepWiki

SwiftAgent is a powerful Swift framework for building AI agents using a declarative SwiftUI-like syntax. It provides a type-safe, composable way to create complex agent workflows while maintaining Swift's expressiveness.

Architecture Overview

graph TB
    subgraph "Core Protocols"
        Step["Step<Input, Output>"]
        Agent["Agent: Step"]
        Model["Model: Step"]
        
        Step --> Agent
        Step --> Model
    end
    
    subgraph "OpenFoundationModels Integration"
        Tool["Tool Protocol"]
        LMS["LanguageModelSession"]
        Generable["@Generable"]
        Prompt["@PromptBuilder"]
        Instructions["@InstructionsBuilder"]
    end
    
    subgraph "Built-in Steps"
        subgraph "Transform Steps"
            Transform["Transform"]
            Map["Map"]
            Reduce["Reduce"]
            Join["Join"]
        end
        
        subgraph "Control Flow"
            Loop["Loop"]
            Parallel["Parallel"]
            Race["Race"]
            WaitForInput["WaitForInput"]
        end
        
        subgraph "AI Generation"
            Generate["Generate<T>"]
            GenerateText["GenerateText"]
        end
    end
    
    subgraph "State Management"
        Memory["@Memory"]
        Relay["Relay<T>"]
        Session["@Session"]
    end
    
    subgraph "Safety & Monitoring"
        Guardrails["Guardrails"]
        Monitor["Monitor"]
        Tracing["Distributed Tracing"]
    end
    
    subgraph "Tools"
        ReadTool["ReadTool"]
        WriteTool["WriteTool"]
        EditTool["EditTool"]
        MultiEditTool["MultiEditTool"]
        GrepTool["GrepTool"]
        GlobTool["GlobTool"]
        GitTool["GitTool"]
        ExecuteCommandTool["ExecuteCommandTool"]
        URLFetchTool["URLFetchTool"]
    end
    
    Step --> Transform
    Step --> Map
    Step --> Loop
    Step --> Parallel
    Step --> Generate
    Step --> GenerateText
    
    Agent --> Guardrails
    Step --> Monitor
    Step --> Tracing
    
    Generate --> LMS
    GenerateText --> LMS
    Session --> LMS
    
    Tool --> ReadTool
    Tool --> WriteTool
    Tool --> EditTool
    Tool --> ExecuteCommandTool
Loading

Features

  • 🎯 Declarative Syntax: Build agents using familiar SwiftUI-like syntax
  • 🔄 Composable Steps: Chain multiple steps together seamlessly with StepBuilder
  • 🛠️ Type-Safe Tools: Define and use tools with compile-time type checking
  • 🤖 Model-Agnostic: Works with any AI model through OpenFoundationModels
  • 📦 Modular Design: Create reusable agent components
  • 🔄 Async/Await Support: Built for modern Swift concurrency
  • 🎭 Protocol-Based: Flexible and extensible architecture
  • 📊 State Management: Memory and Relay for state handling
  • 🎨 @Session: Elegant session management with property wrapper
  • 🏗️ Builder APIs: Dynamic Instructions and Prompt construction with result builders
  • 🔍 Monitoring: Built-in monitoring and distributed tracing support
  • 📡 OpenTelemetry: Industry-standard distributed tracing with swift-distributed-tracing
  • 🛡️ Guardrails: Safety checks for input/output validation
  • ⚙️ Chain Support: Chain up to 8 steps with type-safe composition

Core Components

Steps

Steps are the fundamental building blocks in SwiftAgent. They process input and produce output in a type-safe manner:

public protocol Step<Input, Output> {
    associatedtype Input: Sendable
    associatedtype Output: Sendable
    
    func run(_ input: Input) async throws -> Output
}

Agents

Agents are high-level abstractions that combine steps to create complex workflows:

public protocol Agent: Step {
    associatedtype Body: Step
    
    @StepBuilder var body: Self.Body { get }
    var maxTurns: Int { get }
    var guardrails: [any Guardrail] { get }
}

Session Management

SwiftAgent provides elegant session management through the @Session property wrapper, enabling reusable and shared language model sessions across your agents.

@Session Property Wrapper

The @Session wrapper simplifies session creation and management:

struct MyAgent {
    // With explicit initialization
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey),
        instructions: Instructions("You are a helpful assistant")
    )
    
    // With custom configuration
    @Session
    var customSession = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are an expert")
    }
}

Using Sessions with Generate Steps

Pass sessions to Generate steps using the $ prefix for Relay access:

struct ContentAgent {
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a content creator")
    }
    
    var body: some Step {
        GenerateText(session: $session) { input in
            Prompt {
                "Create content about: \(input)"
                if detailed {
                    "Include comprehensive details"
                }
            }
        }
    }
}

AI Model Integration

SwiftAgent uses OpenFoundationModels for AI model integration, providing a unified interface for multiple AI providers:

Dynamic Instructions with InstructionsBuilder

// Build instructions dynamically with conditions and loops
let session = LanguageModelSession {
    "You are an AI assistant"
    
    if userPreferences.verbose {
        "Provide detailed explanations"
    }
    
    for expertise in userExpertiseAreas {
        "You have expertise in \(expertise)"
    }
    
    "Always be helpful and accurate"
}

Dynamic Prompts with PromptBuilder

// Build prompts dynamically
GenerateText(session: $session) { input in
    Prompt {
        "User request: \(input)"
        
        if includeContext {
            "Context: \(contextInfo)"
        }
        
        for example in relevantExamples {
            "Example: \(example)"
        }
        
        "Please provide a comprehensive response"
    }
}

Using Model Providers

SwiftAgent works with any AI provider through OpenFoundationModels. Configure your preferred provider:

import SwiftAgent
import OpenFoundationModels
// Import your chosen provider package
// e.g., OpenFoundationModelsOpenAI, OpenFoundationModelsOllama, etc.

// Create a session with your chosen model
@Session
var session = LanguageModelSession(
    model: YourModelFactory.create(apiKey: "your-api-key")
) {
    Instructions("You are a helpful assistant.")
}

Available Provider Packages

SwiftAgent is provider-agnostic. Choose from available OpenFoundationModels provider packages:

Built-in Steps

Transform

Convert data from one type to another:

Transform<String, Int> { input in
    Int(input) ?? 0
}

Generate

Generate structured output using AI models with Builder APIs:

@Generable
struct Story {
    @Guide(description: "The story title")
    let title: String
    @Guide(description: "The story content")
    let content: String
}

// Using @Session and PromptBuilder
struct StoryGenerator {
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a creative writer")
    }
    
    var generator: some Step {
        Generate<String, Story>(session: $session) { input in
            Prompt {
                "Write a story about: \(input)"
                "Include vivid descriptions"
                if includeDialogue {
                    "Add realistic dialogue"
                }
            }
        }
    }
}

GenerateText

Generate string output using AI models with dynamic builders:

// Using @Session with shared configuration
struct TextGenerator {
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a creative writer")
    }
    
    func generate(_ topic: String) -> some Step {
        GenerateText(session: $session) { input in
            Prompt {
                "Write about: \(topic)"
                "Input: \(input)"
            }
        }
    }
}

Loop

Iterate with a condition:

Loop(max: 5) { input in
    ProcessingStep()
} until: { output in
    output.meetsQualityCriteria
}

Map

Process collections:

Map<[String], [Int]> { item, index in
    Transform { str in
        str.count
    }
}

Parallel

Execute steps concurrently:

Parallel<String, Int> {
    CountWordsStep()
    CountCharactersStep()
    CountLinesStep()
}

Built-in Tools

SwiftAgent includes a comprehensive suite of tools for file operations, searching, command execution, and more. See the Tool Reference section below for detailed information about each tool.

Quick Examples

File Operations

// Reading files
let readTool = ReadTool()
let content = try await readTool.call(ReadInput(path: "config.json", startLine: 1, endLine: 50))

// Writing files
let writeTool = WriteTool()
let result = try await writeTool.call(WriteInput(path: "output.txt", content: "Hello, World!"))

// Editing files
let editTool = EditTool()
let edited = try await editTool.call(EditInput(
    path: "main.swift",
    oldString: "print(\"old\")",
    newString: "print(\"new\")",
    replaceAll: "true"
))

Search Operations

// Search with grep
let grepTool = GrepTool()
let matches = try await grepTool.call(GrepInput(
    pattern: "TODO:",
    filePattern: "*.swift",
    basePath: "./src",
    ignoreCase: "false",
    contextBefore: 2,
    contextAfter: 2
))

// Find files with glob
let globTool = GlobTool()
let files = try await globTool.call(GlobInput(
    pattern: "**/*.md",
    basePath: ".",
    fileType: "file"
))

System Operations

// Execute commands
let executeTool = ExecuteCommandTool()
let output = try await executeTool.call(ExecuteCommandInput(
    command: "swift build",
    timeout: 30
))

// Git operations
let gitTool = GitTool()
let status = try await gitTool.call(GitInput(
    command: "status",
    args: "--short"
))

// Fetch URLs
let urlTool = URLFetchTool()
let webpage = try await urlTool.call(URLInput(url: "https://api.example.com/data"))

Tool Reference

Tool Name Purpose Main Features Common Use Cases
ReadTool Read file contents with line numbers • Line number formatting (123→content)
• Range selection (startLine, endLine)
• UTF-8 text file support
• Max file size: 1MB
• View source code
• Read configuration files
• Inspect specific line ranges
• Debug file contents
WriteTool Write content to files • Create new files or overwrite existing
• Automatic parent directory creation
• Atomic write operations
• UTF-8 encoding only
• Save generated content
• Create configuration files
• Export data
• Write logs or reports
EditTool Find and replace text in files • Single or all occurrences replacement
• Preview changes before applying
• Atomic operations
• Validates old/new strings
• Fix bugs in code
• Update configuration values
• Refactor variable names
• Correct typos
MultiEditTool Apply multiple edits in one transaction • Batch find/replace operations
• Transactional (all or nothing)
• Order-preserving execution
• JSON-based edit specification
• Complex refactoring
• Multiple related changes
• Atomic updates
• Code migrations
GrepTool Search file contents using regex • Regular expression patterns
• Case-insensitive option
• Context lines (before/after)
• Multi-file search
• Find TODO comments
• Locate function usage
• Search error messages
• Code analysis
GlobTool Find files using glob patterns • Wildcard patterns (*, **, ?)
• File type filtering
• Recursive directory traversal
• Sorted results
• Find files by extension
• List directory contents
• Discover project structure
• Batch file operations
ExecuteCommandTool Execute shell commands • Configurable timeout
• stdout/stderr capture
• Working directory support
• Process control
• Build projects
• Run tests
• System operations
• Script execution
GitTool Perform Git operations • All git commands supported
• Argument passing
• Repository operations
• Output capture
• Version control
• Commit changes
• Branch management
• Check status
URLFetchTool Fetch content from URLs • HTTP/HTTPS support
• Content type handling
• Error handling
• Response parsing
• API calls
• Web scraping
• Data fetching
• External integrations

Converting Steps to Tools

SwiftAgent allows you to use any Step as a Tool when it meets certain requirements. This enables seamless integration of your custom Steps with AI models, promoting code reuse and maintainability.

Requirements for Step-to-Tool Conversion

A Step can be used directly as a Tool when it:

  1. Conforms to both Step and Tool protocols
  2. Input conforms to ConvertibleFromGeneratedContent & Generable
  3. Output conforms to PromptRepresentable
  4. Conforms to Sendable for thread safety
  5. Defines name and description properties for Tool identification

Simple Example

import SwiftAgent
import OpenFoundationModels

// Define a Step that also conforms to Tool
struct UppercaseStep: Step, Tool, Sendable {
    // Required Tool properties
    let name = "uppercase"
    let description = "Converts text to uppercase"
    
    // Step implementation
    func run(_ input: String) async throws -> String {
        input.uppercased()
    }
}

// The Step can now be used as a Tool
let session = LanguageModelSession(
    model: OpenAIModelFactory.gpt4o(apiKey: apiKey),
    tools: [UppercaseStep()]  // Using Step as Tool
) {
    Instructions("You are a text processing assistant")
}

Advanced Example with Structured Input/Output

import SwiftAgent
import OpenFoundationModels

// Define structured input using @Generable
@Generable
struct CalculationInput: Sendable {
    @Guide(description: "First number for calculation")
    let a: Double
    @Guide(description: "Second number for calculation")
    let b: Double
    @Guide(description: "Operation: add, subtract, multiply, divide")
    let operation: String
}

// Define a calculation Step that can be used as a Tool
struct CalculatorStep: Step, Tool, Sendable {
    // Tool identification
    let name = "calculator"
    let description = "Performs basic arithmetic operations"
    
    // Step implementation
    func run(_ input: CalculationInput) async throws -> String {
        let result: Double = switch input.operation {
        case "add": input.a + input.b
        case "subtract": input.a - input.b
        case "multiply": input.a * input.b
        case "divide": input.b != 0 ? input.a / input.b : 0
        default: 0
        }
        return "Result: \(result)"
    }
}

// Use in an AI session
let session = LanguageModelSession(
    model: OpenAIModelFactory.gpt4o(apiKey: apiKey),
    tools: [CalculatorStep()]
) {
    Instructions("You are a math assistant. Use the calculator tool for computations.")
}

How It Works

The Tool+Step extension automatically provides:

  • Arguments type alias pointing to your Step's Input type
  • parameters property derived from Input's GenerationSchema
  • call(arguments:) method that delegates to the Step's run() method
  • Automatic name inference from the Step type (can be overridden)

This means you write your Step logic once and can use it both:

  • As a Step in agent workflows for composable processing
  • As a Tool for AI models to invoke during generation

Best Practices

  1. Keep Steps focused: Each Step should do one thing well
  2. Use @Generable for complex inputs: This ensures proper schema generation
  3. Provide clear descriptions: Help the AI understand when to use your tool
  4. Make outputs PromptRepresentable: Return strings or implement the protocol
  5. Consider thread safety: Ensure your Step is Sendable for concurrent use

Tool Integration with AI Models

All tools implement the OpenFoundationModels.Tool protocol and can be used with AI models:

let session = LanguageModelSession(
    model: OpenAIModelFactory.gpt4o(apiKey: apiKey),
    tools: [
        // Built-in tools
        ReadTool(),
        WriteTool(),
        EditTool(),
        GrepTool(),
        ExecuteCommandTool(),
        
        // Your custom Steps as Tools
        UppercaseStep(),
        CalculatorStep()
    ]
) {
    Instructions("You are a code assistant with file system access.")
}

Tool Input/Output Types

All tools use @Generable structs for type-safe input and provide structured output:

// Example: ReadTool
@Generable
struct ReadInput {
    @Guide(description: "File path to read")
    let path: String
    @Guide(description: "Starting line number (1-based, 0 for beginning)")
    let startLine: Int
    @Guide(description: "Ending line number (0 for end of file)")
    let endLine: Int
}

// Output includes metadata
struct ReadOutput {
    let content: String        // Formatted with line numbers
    let totalLines: Int       // Total lines in file
    let linesRead: Int        // Lines actually read
    let path: String          // Normalized path
    let startLine: Int        // Actual start line
    let endLine: Int          // Actual end line
}

Examples

Simple Writer Agent

import SwiftAgent
import OpenFoundationModels

public struct Writer: Agent {
    public typealias Input = String
    public typealias Output = String
    
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a creative writer")
    }
    
    public init() {}
    
    public var body: some Step<Input, Output> {
        GenerateText(session: $session) { input in
            Prompt {
                "Request: \(input)"
                "Create an engaging narrative"
            }
        }
    }
}

// Usage
let writer = Writer()
let story = try await writer.run("Write a story about a time-traveling scientist")

Code Analysis Agent with Tools

import SwiftAgent
import OpenFoundationModels
import AgentTools

struct CodeAnalyzer: Agent {
    typealias Input = String
    typealias Output = AnalysisResult
    
    @Session
    var session: LanguageModelSession
    
    init(model: any LanguageModel) {
        self._session = Session(wrappedValue: LanguageModelSession(
            model: model,
            tools: [ReadTool(), GrepTool(), GitTool()]
        ) {
            Instructions {
                "You are a code analysis expert"
                "Analyze the codebase and provide insights"
                "Focus on code quality and best practices"
            }
        })
    }
    
    var body: some Step<Input, Output> {
        Generate<String, AnalysisResult>(session: $session) { request in
            Prompt {
                "Analyze the following: \(request)"
                "Use available tools to examine the code"
                "Provide actionable recommendations"
            }
        }
    }
}

@Generable
struct AnalysisResult {
    @Guide(description: "Summary of findings")
    let summary: String
    
    @Guide(description: "List of issues found")
    let issues: String  // Space-separated list
    
    @Guide(description: "Recommendations")
    let recommendations: String
}

Multi-Step Research Agent

struct ResearchAgent: Agent {
    typealias Input = String
    typealias Output = ResearchReport
    
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a research expert")
    }
    
    var body: some Step<Input, Output> {
        // Step 1: Generate search queries
        Transform<String, SearchQueries> { topic in
            SearchQueries(topic: topic)
        }
        
        // Step 2: Search in parallel
        Map<SearchQueries, [SearchResult]> { query, _ in
            URLFetchTool().call(URLInput(url: query.url))
                .map { SearchResult(content: $0) }
        }
        
        // Step 3: Analyze results
        Generate<[SearchResult], ResearchReport>(session: $session) { results in
            Prompt {
                "Synthesize these search results:"
                for result in results {
                    "- \(result.content)"
                }
                "Create a comprehensive report with key findings"
            }
        }
    }
    
    var guardrails: [any Guardrail] {
        [ContentSafetyGuardrail(), TokenLimitGuardrail(maxTokens: 4000)]
    }
}

Interactive Chat Agent with Memory

struct ChatAgent: Agent {
    typealias Input = String
    typealias Output = String
    
    @Memory var conversationHistory: [String] = []
    
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: apiKey)
    ) {
        Instructions("You are a helpful conversational assistant")
    }
    
    var body: some Step<Input, Output> {
        Transform<String, String> { input in
            // Add to conversation history
            conversationHistory.append("User: \(input)")
            return input
        }
        
        GenerateText(session: $session) { input in
            Prompt {
                "Conversation history:"
                for message in conversationHistory.suffix(10) {
                    message
                }
                ""
                "Current message: \(input)"
                "Respond naturally and helpfully"
            }
        }
        
        Transform<String, String> { response in
            // Save assistant response
            conversationHistory.append("Assistant: \(response)")
            return response
        }
    }
}

Requirements

  • Swift 6.0+
  • iOS 18.0+ / macOS 15.0+
  • Xcode 15.0+

Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/1amageek/SwiftAgent.git", branch: "main")
]

Model Provider Packages

SwiftAgent requires a model provider package from the OpenFoundationModels ecosystem. Choose based on your needs:

// For OpenAI models
.package(url: "https://github.com/1amageek/OpenFoundationModels-OpenAI.git", branch: "main")

// For local models via Ollama
.package(url: "https://github.com/1amageek/OpenFoundationModels-Ollama.git", branch: "main")

// For Anthropic Claude models
.package(url: "https://github.com/1amageek/OpenFoundationModels-Anthropic.git", branch: "main")

// Additional providers available - check OpenFoundationModels documentation

Quick Start Example

// Complete Package.swift example
import PackageDescription

let package = Package(
    name: "MyAgentProject",
    platforms: [.iOS(.v18), .macOS(.v15)],
    products: [
        .executable(name: "MyAgent", targets: ["MyAgent"])
    ],
    dependencies: [
        .package(url: "https://github.com/1amageek/SwiftAgent.git", branch: "main"),
        // Choose your AI provider - example with OpenAI
        .package(url: "https://github.com/1amageek/OpenFoundationModels-OpenAI.git", branch: "main")
    ],
    targets: [
        .executableTarget(
            name: "MyAgent",
            dependencies: [
                .product(name: "SwiftAgent", package: "SwiftAgent"),
                .product(name: "AgentTools", package: "SwiftAgent"),  // Optional: for built-in tools
                .product(name: "OpenFoundationModelsOpenAI", package: "OpenFoundationModels-OpenAI")
            ]
        )
    ]
)

Getting Started

1. Add SwiftAgent to your Package.swift

import PackageDescription

let package = Package(
    name: "MyAgentApp",
    platforms: [.iOS(.v18), .macOS(.v15)],
    dependencies: [
        // Core SwiftAgent framework
        .package(url: "https://github.com/1amageek/SwiftAgent.git", branch: "main"),
        
        // Add your chosen AI provider package
        // Example: OpenAI
        .package(url: "https://github.com/1amageek/OpenFoundationModels-OpenAI.git", branch: "main")
    ],
    targets: [
        .target(
            name: "MyAgentApp",
            dependencies: [
                .product(name: "SwiftAgent", package: "SwiftAgent"),
                .product(name: "AgentTools", package: "SwiftAgent"),  // Optional: for built-in tools
                .product(name: "OpenFoundationModelsOpenAI", package: "OpenFoundationModels-OpenAI")
            ]
        )
    ]
)

2. Set up your environment

Configure your chosen AI provider according to their documentation. For example:

# For OpenAI
export OPENAI_API_KEY="your-api-key"

# For Anthropic
export ANTHROPIC_API_KEY="your-api-key"

# For local models (Ollama)
# Install and configure Ollama according to their documentation

3. Create your first agent

import SwiftAgent
import OpenFoundationModels
import OpenFoundationModelsOpenAI  // Your chosen provider

struct MyAgent: Agent {
    typealias Input = String
    typealias Output = String
    
    @Session
    var session = LanguageModelSession(
        model: OpenAIModelFactory.gpt4o(apiKey: ProcessInfo.processInfo.environment["OPENAI_API_KEY"] ?? "")
    ) {
        Instructions {
            "You are a helpful assistant"
            "Be concise and informative"
        }
    }
    
    var body: some Step<Input, Output> {
        GenerateText(session: $session) { input in
            Prompt {
                "User request: \(input)"
                "Provide a helpful response"
            }
        }
    }
}

4. Run your agent

@main
struct MyApp {
    static func main() async throws {
        let agent = MyAgent()
        let result = try await agent.run("Hello, world!")
        print(result)
    }
}

Advanced Features

Guardrails

Add safety checks to your agents:

struct ContentGuardrail: Guardrail {
    func validate(_ content: String) throws {
        if content.contains("inappropriate") {
            throw GuardrailError.contentViolation
        }
    }
}

struct MyAgent: Agent {
    var guardrails: [any Guardrail] {
        [ContentGuardrail()]
    }
    
    var body: some Step<String, String> {
        // Agent implementation
    }
}

Monitoring & Tracing

SwiftAgent provides two complementary ways to observe step execution:

Monitor - Lightweight Debugging

Use Monitor for simple debugging and logging during development:

GenerateText { input in
    "Process: \(input)"
}
.onInput { input in
    print("Starting with: \(input)")
}
.onOutput { output in
    print("Generated: \(output)")
}
.onError { error in
    print("Failed: \(error)")
}
.onComplete { duration in
    print("Took \(duration) seconds")
}

Distributed Tracing - Production Monitoring

Use trace() for production-grade distributed tracing with OpenTelemetry support:

GenerateText { input in
    "Process: \(input)"
}
.trace("TextGeneration", kind: .client)

// Combine monitoring and tracing
GenerateText { input in
    "Process: \(input)"
}
.onError { error in
    logger.error("Generation failed: \(error)")
}
.trace("TextGeneration")

Integration with Vapor

SwiftAgent automatically integrates with Vapor's distributed tracing:

app.post("analyze") { req async throws -> Response in
    // SwiftAgent traces will be nested under Vapor's request trace
    let agent = MyAgent()
    let result = try await agent.run(input)
    return result
}

The trace hierarchy will look like:

[Trace] Request abc-123
├─ [Span] POST /analyze (Vapor) - 2.5s
│  ├─ [Span] MyAgent - 2.3s
│  │  ├─ [Span] ContentSafetyGuardrail - 0.1s ✓
│  │  ├─ [Span] GenerateText - 2.0s
│  │  └─ [Span] OutputGuardrail - 0.2s ✓
│  └─ [Span] Response serialization - 0.2s

Memory

Maintain state across agent runs:

struct StatefulAgent: Agent {
    @Memory var conversationHistory: [String] = []
    
    var body: some Step<String, String> {
        Transform { input in
            conversationHistory.append(input)
            return conversationHistory.joined(separator: "\n")
        }
    }
}

License

SwiftAgent is available under the MIT license.

Author

@1amageek

Description

  • Swift Tools 6.2.0
View More Packages from this Author

Dependencies

Last updated: Wed Oct 15 2025 04:01:49 GMT-0900 (Hawaii-Aleutian Daylight Time)