Skip to content

autohandai/code-agent-sdk-swift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Code Agent SDK for Swift

SwiftPM package for building Autohand-style code agents in Swift. It provides Agent, Runner, async streams, provider abstractions, tools, hooks, loop strategies, and permission controls.

Beta: this SDK is actively evolving while the Agent SDK APIs stabilize. Pin versions in production and review release notes before upgrading.

Other Programming Languages (Beta)

The Agent SDK is available in multiple beta language packages. Use the same Autohand code-agent model from another programming language:

  • TypeScript - Agent, Run, streaming, and JSON helpers for Node and Bun hosts.
  • Go - idiomatic Go package with context.Context, typed events, and channel-based streaming.
  • Python - async Python package with async for event streams and typed Pydantic models.
  • Java - Java 21 records, sealed events, and virtual-thread-ready APIs.
  • Swift - this SwiftPM package.
  • Rust - async Rust crate with Tokio, typed events, and stream-based runs.
  • C++ - modern C++20 package with CMake targets and typed event callbacks.
  • C# - .NET package with IAsyncEnumerable, CancellationToken, and System.Text.Json.

Requirements

  • Swift 6.0+
  • macOS 14+ or iOS 17+
  • An OpenAI-compatible provider key for live provider-backed runs. For Autohand AI Cloud, set AUTOHAND_AI_API_KEY and use ProviderFactory.create(providerName: "autohandai", ...).

Installation

Add the package to Package.swift:

dependencies: [
    .package(url: "https://github.com/autohandai/code-agent-sdk-swift.git", branch: "main"),
]

Then depend on AgentSDK from your target:

.executableTarget(
    name: "MyAgentApp",
    dependencies: ["AgentSDK"]
)

CLI-backed discovery, goals, and autoresearch

On macOS, AutohandCLIClient adds the same typed replayable autoresearch ledger available in the TypeScript 1.0.3 SDK while preserving the existing direct-provider Agent and Runner APIs:

let client = AutohandCLIClient(configuration: .init(cwd: ".", unrestricted: true))
try client.start()
defer { client.close() }

if try await client.supportsCommand("/autoresearch") {
    let start = try await client.startAutoresearch(.init(
        objective: "Reduce test runtime",
        metricName: "test_ms",
        metricUnit: "ms",
        direction: .lower,
        measureCommand: "swift test"
    ))
    if let instruction = start.instruction {
        _ = try await client.prompt(instruction)
    }
    let history = try await client.autoresearchHistory()
    _ = try await client.stopAutoresearch()
}

Persistent goals use the same seven JSON-RPC operations as the TypeScript SDK:

if case .value(let result) = try await client.createGoal(.init(
    objective: "Ship the Swift SDK",
    tokenBudget: 40_000
)) {
    print(result.ok)
}

_ = try await client.updateGoal(.init(
    status: .paused,
    tokenBudget: .clear
))
let snapshot = try await client.goal()
let templates = try await client.goalTemplates()

For a single high-level lifecycle object, use AutohandSDK. It owns an AutohandCLIClient and exposes typed skill-registry and MCP discovery:

let sdk = AutohandSDK(configuration: .init(cwd: "."))
try sdk.start()
defer { sdk.close() }

let registry = try await sdk.getSkillsRegistry(.init(forceRefresh: true))
let installation = try await sdk.installSkill(.init(
    skillName: "release-readiness",
    scope: .project,
    force: false
))
let servers = try await sdk.listMCPServers()
let tools = try await sdk.listMCPTools(.init(serverName: "filesystem"))
let configs = try await sdk.getMCPServerConfigs()

These methods call autohand.getSkillsRegistry, autohand.installSkill, autohand.mcp.listServers, autohand.mcp.listTools, and autohand.mcp.getServerConfigs with the CLI's exact camel-case wire keys. Installing a skill changes user or project state; discovery calls are read-only.

Use reset() on AutohandCLIClient or AutohandSDK to replace the active conversation and receive its new session ID. Create an expiring browser attachment URL with createBrowserHandoff(_:). Attach one by token with attachBrowserHandoff(_:). Use attachLatestBrowserHandoff() to select the newest handoff automatically. Start a bounded autonomous run with typed limits through startAutoMode(_:). Inspect progress and checkpoint metadata with autoModeStatus(). Pause an active autonomous run with pauseAutoMode(). Resume it with resumeAutoMode(). Cancel with an optional audit reason through cancelAutoMode(_:). Read typed iteration history with autoModeLog(_:).

AutohandSDK is the macOS CLI-facing API. The cross-platform Agent and Runner remain direct-provider APIs and do not silently launch a subprocess.

AutohandCLIConfiguration also mirrors current CLI session, AGENTS.md, token, skill-source, auto-mode, prompt, feature-flag, and Autohand AI environment settings. A non-nil features value is applied immediately after startup.

Read the replayable autoresearch guide for replay, rescore, comparison, Pareto, pinning, retention, and event semantics.

Quick Start

import AgentSDK
import Foundation

let provider = OpenAIProvider(apiKey: ProcessInfo.processInfo.environment["OPENAI_API_KEY"]!)

let agent = Agent(
    name: "Reviewer",
    instructions: "Review code for correctness and maintainability.",
    tools: [.readFile, .bash],
    maxTurns: 10,
    model: ModelID("gpt-4o"),
    provider: provider,
    cwd: FileManager.default.currentDirectoryPath
)

let result = try await Runner.runSync(
    agent: agent,
    prompt: "Summarize this package"
)

print(result)

Only the names in Agent.tools are advertised to the provider and executable. An empty list exposes no tools. When a PermissionManager is installed on Runner, every requested tool is checked before its implementation runs.

Streaming

let stream = Runner.runStream(
    agent: agent,
    prompt: "Review Sources/Types.swift"
)

for try await event in stream {
    switch event.type {
    case .content:
        print(event.data ?? "", terminator: "")
    case .toolCall:
        print("\n[tool: \(event.tool?.rawValue ?? "unknown")]")
    case .done:
        print("\nDone")
    default:
        break
    }
}

Documentation

Development

swift build
swift test
Scripts/benchmark-startup.sh

About

Autohand Code Agent SDK for Swift: SwiftPM package for code agents with async streams, tools, hooks, permissions, and examples.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages