Examples Tutorial
June 14, 2026 · View on GitHub
Complete runnable examples demonstrating Open Agent SDK features. Each example is a standalone Swift executable you can run with a single command.
Prerequisites
- Swift 6.1+ and macOS 13+
- API Key — set one of the following environment variables:
# Option 1: OpenAI-compatible API (GLM, Ollama, OpenRouter, etc.) — default
export CODEANY_API_KEY=your-key
export CODEANY_BASE_URL=https://open.bigmodel.cn/api/coding/paas/v4
export CODEANY_MODEL=glm-5.1
# Option 2: Anthropic API (Claude models)
export ANTHROPIC_API_KEY=sk-ant-...
Tip: Add the
exportlines to your~/.zshrcor~/.bashrcso they persist across sessions. Or copy.envfrom the project root and adjust the values.
Quick Start
# 1. Clone and enter the project
git clone https://github.com/terryso/open-agent-sdk-swift.git
cd open-agent-sdk-swift
# 2. Build the project (first time only — resolves all dependencies)
swift build
# 3. Run your first example
swift run BasicAgent
That's it! The agent will send a prompt to the LLM and print the response.
All Examples
1. BasicAgent — Agent Creation & Simple Query
The simplest example. Creates an agent, sends a blocking prompt, and prints the response with usage stats.
swift run BasicAgent
What you'll learn:
- Creating an agent with
createAgent(options:) - Blocking query with
agent.prompt() - Reading
QueryResultfields (text, status, turns, cost, tokens) - Using Anthropic vs OpenAI-compatible providers
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
model: "claude-sonnet-4-6",
systemPrompt: "You are a helpful assistant.",
permissionMode: .bypassPermissions
))
let result = await agent.prompt("Explain what an AI agent is in one paragraph.")
2. StreamingAgent — Real-Time Streaming Responses
Shows how to consume agent responses in real-time using AsyncStream<SDKMessage>.
swift run StreamingAgent
What you'll learn:
- Streaming with
agent.stream() - Event types:
partialMessage,toolUse,toolResult,result,system - Budget tracking with
maxBudgetUsd
Key code:
for await message in agent.stream("Write a haiku about programming.") {
switch message {
case .partialMessage(let data): print(data.text, terminator: "")
case .result(let data): print("Done: \(data.numTurns) turns, $\(data.totalCostUsd)")
default: break
}
}
3. CustomTools — Defining Custom Tools
Demonstrates defineTool() with Codable input types, String vs ToolExecuteResult returns, and permission control.
swift run CustomTools
What you'll learn:
- Creating tools with
defineTool()and Codable input structs - JSON Schema definitions for tool parameters
- String return vs
ToolExecuteResult(success/error) return types - Read-only tools with
isReadOnly: true - Three permission control approaches: closure, Policy, and mode
Key code:
struct WeatherInput: Codable { let city: String }
let weatherTool = defineTool(
name: "get_weather",
description: "Get the current weather for a city",
inputSchema: [...]
) { (input: WeatherInput, context: ToolContext) -> String in
return "Weather in \(input.city): 22C, sunny"
}
4. CustomSystemPromptExample — Specialized Agent Roles
Shows how to customize agent behavior through system prompts. Creates a "code review expert" agent.
swift run CustomSystemPromptExample
What you'll learn:
- Using
systemPromptto define agent persona and output format - How system prompts shape response style and structure
- Running a domain-specific agent (code reviewer)
5. PromptAPIExample — Blocking API with Built-in Tools
Demonstrates agent.prompt() with all 10 core tools registered. The agent autonomously executes tools and returns the final result.
swift run PromptAPIExample
What you'll learn:
- Using
getAllBaseTools(tier: .core)to register all core tools - Blocking API where the agent uses tools autonomously
- Handling
QueryResultstatus and error cases
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
tools: getAllBaseTools(tier: .core)
))
let result = await agent.prompt("Analyze the project structure...")
6. MultiToolExample — Multi-Tool Orchestration (Streaming)
Shows an agent autonomously coordinating multiple tools (Glob, Bash, Read) using the streaming API.
swift run MultiToolExample
What you'll learn:
- Streaming with
agent.stream()while tools execute - Real-time event handling for tool calls and results
- Agent-driven multi-step task orchestration
7. SubagentExample — Agent Delegation
Demonstrates the main agent delegating tasks to sub-agents via the Agent tool.
swift run SubagentExample
What you'll learn:
- Creating a coordinator agent with
createAgentTool() - How the main agent spawns Explore-type sub-agents
- Sub-agents use a restricted tool set (Read, Glob, Grep, Bash)
- Results flow back from sub-agent to main agent
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
tools: getAllBaseTools(tier: .core) + [createAgentTool()]
))
8. PermissionsExample — Permission Policy Comparison
Runs three agents side-by-side, each with a different permission policy, to demonstrate access control.
swift run PermissionsExample
What you'll learn:
ToolNameAllowlistPolicy— allow only specific tool namesReadOnlyPolicy— allow onlyisReadOnly == truetoolsbypassPermissions— unrestricted access (for comparison)- Bridging policies to callbacks with
canUseTool(policy:)
9. MCPIntegration — MCP Server Basics
Introduces MCP (Model Context Protocol) integration with InProcessMCPServer and stdio configurations.
swift run MCPIntegration
What you'll learn:
- Creating an
InProcessMCPServerwith custom tools - MCP tool namespacing (
mcp__{serverName}__{toolName}) - Using
asConfig()to generate SDK configuration - Stdio MCP server configuration for external tool servers
Key code:
let server = InProcessMCPServer(name: "my-tools", version: "1.0.0", tools: [echoTool], cwd: "/tmp")
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
mcpServers: ["my-tools": await server.asConfig()]
))
10. AdvancedMCPExample — Multi-Tool MCP with Error Handling
Advanced MCP example with multiple tools and error handling patterns.
swift run AdvancedMCPExample
What you'll learn:
- Registering multiple tools in a single MCP server
- Error handling with
ToolExecuteResult(isError: true) - Running multiple queries with the same MCP agent
- Namespace verification (
mcp__utility__get_weather, etc.)
11. SessionsAndHooks — Session Persistence & Lifecycle Hooks
Demonstrates session persistence (save/resume conversations) and hook registry for lifecycle events.
swift run SessionsAndHooks
What you'll learn:
SessionStorefor saving/loading/forking sessionsHookRegistryfor pre/post tool execution hookssessionStart/sessionEndlifecycle hooks- Session resume across processes using
sessionId
Key code:
let sessionStore = SessionStore()
let hookRegistry = HookRegistry()
await hookRegistry.register(.preToolUse, definition: HookDefinition(
matcher: "Bash",
handler: { input in return HookOutput(message: "Blocked", block: true) }
))
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
sessionStore: sessionStore,
sessionId: "my-session",
hookRegistry: hookRegistry
))
12. SkillsExample — Skills System (Built-in & Custom)
Demonstrates the Skills system — registering built-in skills (commit, review, simplify, debug, test), creating custom skills, and executing skills via the LLM.
swift run SkillsExample
What you'll learn:
- Initializing built-in skills via
BuiltInSkills - Registering and discovering skills with
SkillRegistry - Creating custom skills with
Skill(name:description:promptTemplate:toolRestrictions:) - Agent executing skills via
createSkillTool(registry:)
Key code:
let registry = SkillRegistry()
registry.register(BuiltInSkills.commit)
registry.register(BuiltInSkills.review)
let customSkill = Skill(
name: "explain", description: "Explain code in detail",
promptTemplate: "Read the files and explain...", toolRestrictions: [.bash, .read]
)
registry.register(customSkill)
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
tools: getAllBaseTools(tier: .core) + [createSkillTool(registry: registry)]
))
13. SandboxExample — Sandbox Configuration & Enforcement
Shows how to configure path and command restrictions to control Agent's filesystem and Bash operations.
swift run SandboxExample
What you'll learn:
- Configuring
SandboxSettingswith path allowlists/denylists - Command blacklisting (
deniedCommands) and whitelisting (allowedCommands) - Path traversal protection and symlink resolution
- Shell metacharacter detection for bypass prevention
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
sandbox: SandboxSettings(
allowedReadPaths: ["/project/"],
allowedWritePaths: ["/project/src/"],
deniedCommands: ["rm", "sudo"]
)
))
14. LoggerExample — Structured Logging System
Demonstrates configurable log levels (none/error/warn/info/debug) and output targets (console/file/custom) for SDK diagnostic events.
swift run LoggerExample
What you'll learn:
- Configuring log levels via
AgentOptions.logLevel - Output targets:
.console,.file(URL),.custom(closure) - Structured JSON log format (timestamp, level, module, event, data)
- Zero-overhead verification when
logLevel = .none
Key code:
Logger.configure(level: .debug, output: .custom { jsonLine in
print("[SDK LOG] \(jsonLine)")
})
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
logLevel: .debug,
logOutput: .custom { line in myHandler(line) }
))
15. ModelSwitchingExample — Runtime Model Switching
Shows how to dynamically switch LLM models mid-conversation with per-model cost tracking.
swift run ModelSwitchingExample
What you'll learn:
- Switching models with
agent.switchModel() - Per-model token usage and cost breakdown in
QueryResult - Error handling for invalid model names
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey, model: "claude-sonnet-4-6"
))
let result1 = await agent.prompt("Simple question...")
try agent.switchModel("claude-opus-4-6")
let result2 = await agent.prompt("Complex analysis...")
// result2.usage shows separate costs per model
16. QueryAbortExample — Query Cancellation
Demonstrates how to cancel running Agent queries using Swift's Task.cancel() and retrieve partial results.
swift run QueryAbortExample
What you'll learn:
- Launching queries in Swift
Taskfor cancellation support - Cancelling with
Task.cancel()oragent.interrupt() - Handling
QueryResult.isCancelledand partial tool results - Stream cancellation via
SDKMessageevents
Key code:
let task = Task {
for await message in agent.stream("Long-running task...") {
// process events
}
}
// Cancel after delay
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
task.cancel()
}
17. ContextInjectionExample — File Cache & Context Injection
Shows file caching with LRU eviction, Git status auto-injection, and project document discovery (CLAUDE.md/AGENT.md).
swift run ContextInjectionExample
What you'll learn:
- Configuring
FileCacheparameters (maxEntries, maxSizeBytes) - Cache hit/miss statistics and eviction tracking
- Git context collection (
<git-context>in system prompt) - Project document discovery (
<project-instructions>from CLAUDE.md/AGENT.md) - Cache invalidation on file writes
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
projectRoot: "/path/to/project"
))
// System prompt automatically includes <git-context> and <project-instructions>
18. MultiTurnExample — Multi-Turn Conversation with SessionStore
Demonstrates multi-turn conversations with context retention across queries using SessionStore.
swift run MultiTurnExample
What you'll learn:
- Executing sequential queries on the same Agent instance
- Context retention across turns (Agent remembers earlier messages)
- Inspecting conversation history with
agent.getMessages() - Streaming support in multi-turn conversations
Key code:
let sessionStore = SessionStore()
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
sessionStore: sessionStore,
sessionId: "conversation-1"
))
// Turn 1
let result1 = await agent.prompt("My name is Nick.")
// Turn 2 — Agent remembers the name from turn 1
let result2 = await agent.prompt("What is my name?")
19. OpenAICompatExample — OpenAI-Compatible API Providers
Shows how to use OpenAI-compatible APIs (GLM, DeepSeek, Qwen, Ollama, OpenRouter, etc.) with the same Agent API.
swift run OpenAICompatExample
What you'll learn:
- Configuring
provider: .openaiwith custombaseURL - Using environment variables (
CODEANY_API_KEY,CODEANY_BASE_URL,CODEANY_MODEL) - Comparing Anthropic vs OpenAI-compatible provider setup
- Running tools with OpenAI-compatible providers
Key code:
let agent = createAgent(options: AgentOptions(
provider: .openai,
apiKey: ProcessInfo.processInfo.environment["CODEANY_API_KEY"] ?? "",
model: "glm-5.1",
baseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
permissionMode: .bypassPermissions
))
Compat Verification Examples
These 12 examples verify that the Swift SDK's API surface is fully compatible with the open-agent-sdk-typescript. Each example runs a structured compat report comparing TypeScript SDK fields to their Swift equivalents, printing PASS/MISSING status for every field.
Note: Compat examples are verification tools, not typical usage demos. They're useful for SDK maintainers and contributors to track API parity.
20. CompatCoreQuery — Core Query API Compat
Verifies Swift SDK's prompt()/stream() API covers all TypeScript SDK core usage patterns.
swift run CompatCoreQuery
What you'll learn:
- TypeScript SDK
query()vs Swiftprompt()/stream()mapping - Blocking and streaming query patterns
QueryResultfield parity (text, usage, turns, cost, status)
21. CompatToolSystem — Tool System Compat
Verifies Swift SDK's tool definition and execution matches TypeScript SDK's tool system.
swift run CompatToolSystem
What you'll learn:
defineTool()API parity with TypeScript'stool()function- Tool input schema,
ToolContext, andToolExecuteResultcompatibility - Tool registration and execution lifecycle
22. CompatMessageTypes — Message Types Compat
Verifies Swift SDK's SDKMessage covers all 20 TypeScript SDK message subtypes.
swift run CompatMessageTypes
What you'll learn:
- Full
SDKMessageenum parity (partialMessage, toolUse, toolResult, result, system, etc.) - Streaming event type coverage
- Message data field mapping
23. CompatHooks — Hook System Compat
Verifies Swift SDK's hook system supports all 18 TypeScript SDK HookEvents with matching Input/Output types.
swift run CompatHooks
What you'll learn:
- All lifecycle event types (preToolUse, postToolUse, sessionStart, sessionEnd, etc.)
HookDefinitionmatcher and handler API parityHookInput/HookOutputfield coverage
24. CompatMCP — MCP Integration Compat
Verifies Swift SDK supports all TypeScript SDK MCP server configuration types and runtime management.
swift run CompatMCP
What you'll learn:
- Server config types: stdio, SSE, HTTP, in-process
McpStdioConfig,McpSseConfigfield parity- Runtime MCP server lifecycle management
25. CompatSessions — Session Management Compat
Verifies Swift SDK's session API covers all TypeScript SDK session operations.
swift run CompatSessions
What you'll learn:
SessionStoreoperations: save, load, fork, list, rename, tag, delete- Session configuration options parity
- Session ID management and auto-restore
26. CompatQueryMethods — Query Object Methods Compat
Verifies Swift SDK provides all TypeScript SDK Query object runtime control methods.
swift run CompatQueryMethods
What you'll learn:
- Runtime controls: abort, interrupt, status check
- Query lifecycle methods mapping
- Partial result retrieval compatibility
27. CompatOptions — Agent Options Compat
Verifies Swift SDK's AgentOptions/SDKConfiguration covers all TypeScript SDK Options fields.
swift run CompatOptions
What you'll learn:
- All
AgentOptionsfields and their TypeScript equivalents - Configuration inheritance and defaults
- Environment variable mapping
28. CompatPermissions — Permission System Compat
Verifies Swift SDK's permission system covers all TypeScript SDK permission types and operations.
swift run CompatPermissions
What you'll learn:
- Permission mode parity (bypassPermissions, acceptEdits, default, etc.)
- Custom authorization callback API
- Policy composition compatibility
29. CompatSubagents — Subagent System Compat
Verifies Swift SDK's subagent system covers TypeScript SDK's AgentDefinition and Agent tool usage.
swift run CompatSubagents
What you'll learn:
createAgentTool()and agent spawning API parity- Sub-agent type support (Explore, Plan, etc.)
- Team/task coordination field coverage
30. CompatThinkingModel — Thinking & Model Config Compat
Verifies Swift SDK's ThinkingConfig and model configuration are fully compatible with TypeScript SDK.
swift run CompatThinkingModel
What you'll learn:
ThinkingConfigoptions (budget tokens, type)ModelInfofields and model switching parity- Extended thinking and reasoning control
31. CompatSandbox — Sandbox Configuration Compat
Verifies Swift SDK's sandbox configuration covers all TypeScript SDK sandbox options.
swift run CompatSandbox
What you'll learn:
SandboxSettingsfull field coverage (paths, commands, network, ripgrep)SandboxNetworkConfigandRipgrepConfigparity- Path traversal protection and shell filtering options
32. EventBusExample — Runtime Event Layer (Epic 26)
Demonstrates the EventBus: basic publish/subscribe, type-filtered subscription, multiple concurrent subscribers, and buffering behavior.
swift run EventBusExample
No API key required — this example publishes synthetic events.
What you'll learn:
- Creating an
EventBus()and subscribing to all events - Publishing typed events (
SessionCreatedEvent,AgentStartedEvent,ToolStartedEvent, etc.) - Type-filtered subscription —
bus.subscribe(ToolStartedEvent.self)receives only that type - Multiple concurrent subscribers (CLI logger, cost monitor, tool tracer)
- Buffer policy:
.bufferingNewest(100)— slow consumers don't block publishers
Key code:
let bus = EventBus()
// Subscribe to all events
let (subId, stream) = await bus.subscribe()
// Subscribe to specific type only
let toolStream = bus.subscribe(ToolStartedEvent.self)
// Publish events
await bus.publish(SessionCreatedEvent(sessionId: "sess-001", task: "Analyze", model: "claude-sonnet-4-6"))
await bus.publish(ToolStartedEvent(sessionId: "sess-001", toolName: "Read", toolUseId: "tu_01", input: "/data/file.csv"))
// Unsubscribe
await bus.unsubscribe(subId)
33. SSEBridgeExample — EventBus to SSE Pipeline (Epic 28)
Demonstrates the full SSE bridge pipeline: EventBus → EventBusBridge → EventBroadcaster → SSE stream. Also shows real-time token streaming via LLMTokenStreamEvent.
swift run SSEBridgeExample
Requires API key — set CODEANY_API_KEY or ANTHROPIC_API_KEY.
What you'll learn:
- Building the SSE pipeline:
EventBusBridge(eventBus:broadcaster:runId:) - Passing
eventBusandemitTokenStreamtoAgentOptions - Subscribing to raw EventBus events and SSE events in parallel
- Using
EventBroadcaster.getReplayBuffer()for disconnected client catch-up AgentSSEEvent.encodeToSSE()for SSE wire format
Key code:
let eventBus = EventBus()
let broadcaster = EventBroadcaster()
let bridge = EventBusBridge(eventBus: eventBus, broadcaster: broadcaster, runId: "run-1")
await bridge.start()
// Create agent with EventBus + token streaming
let agent = createAgent(options: AgentOptions(
apiKey: "sk-...",
eventBus: eventBus,
emitTokenStream: true
))
34. SkillWriterExample — Skill Persistence to Disk
Demonstrates SkillWriter for persisting skills to the filesystem as SKILL.md files with YAML frontmatter.
swift run SkillWriterExample
No API key required — pure local file operations.
What you'll learn:
- Writing skills to disk with
SkillWriter.write(skill:to:) - Previewing SKILL.md content with
SkillWriter.buildSKILLMd() - YAML frontmatter generation (name, description, aliases, model override)
- Complex skills with special characters in descriptions
Key code:
let skill = Skill(
name: "summarize",
description: "Summarize a file or text into key points",
aliases: ["sum"],
promptTemplate: "Read the content and produce a summary..."
)
let skillDir = try SkillWriter.write(skill: skill, to: skillsDir)
35. ReviewOrchestratorExample — Review Scheduling & Configuration
Demonstrates ReviewOrchestrator configuration including promptSuffix for extending review prompts and additionalReviewTools for injecting custom tools.
swift run ReviewOrchestratorExample
No API key required — demonstrates configuration and scheduling logic only.
What you'll learn:
- Configuring
ReviewScheduleConfig(intervals, min messages, model override) - Extending review agent instructions with
ReviewAgentConfig.promptSuffix - Injecting custom tools via
additionalReviewTools - Simulating
shouldReview()scheduling with different message counts
Key code:
let orchestrator = ReviewOrchestrator(
scheduleConfig: ReviewScheduleConfig(memoryReviewInterval: 4, skillReviewInterval: 6),
factStore: factStore,
skillRegistry: registry,
skillEvolver: evolver,
usageStore: usageStore,
skillsDir: "/path/to/skills",
additionalReviewTools: [customMemoryTool]
)
let (doMemory, doSkill) = orchestrator.shouldReview(sessionId: "s1", messageCount: 8, config: config)
36. EnvInjectionExample — Environment Variable Injection
Demonstrates how to inject custom environment variables into tool execution context via AgentOptions.env, automatically forwarded to BashTool subprocesses and accessible in custom tools via ToolContext.env.
swift run EnvInjectionExample
Requires API key — set CODEANY_API_KEY or ANTHROPIC_API_KEY.
What you'll learn:
- Setting
AgentOptions.envto inject custom environment variables - BashTool automatically receives
ToolContext.envin subprocess environment - Reading injected env vars from custom tools via
context.env
Key code:
let agent = createAgent(options: AgentOptions(
apiKey: apiKey,
env: ["MY_APP_STAGE": "staging", "MY_APP_REGION": "us-west-2"]
))
// BashTool subprocess sees MY_APP_STAGE and MY_APP_REGION
// Custom tools read via: context.env?["MY_APP_STAGE"]
37. MessageSummaryExample — Message Summaries in LLM Events
Demonstrates MessageSummary with content preview in LLMRequestStartedEvent, showing role, content length, and text preview for each message sent to the LLM.
swift run MessageSummaryExample
Requires API key — set CODEANY_API_KEY or ANTHROPIC_API_KEY.
What you'll learn:
MessageSummaryfields:role,contentLength,preview- Subscribing to
LLMRequestStartedEventvia type-filteredEventBus.subscribe() - Observing how message summaries grow across multi-turn conversations
Key code:
let eventBus = EventBus()
let stream = await eventBus.subscribe(LLMRequestStartedEvent.self)
// Each event carries event.messages: [MessageSummary]
for summary in event.messages {
print("\(summary.role) (\(summary.contentLength) chars): \"\(summary.preview)\"")
}
38. ClaudeCodeCompatExample — Epic 29 Claude Code Skill/Subagent Compatibility
Verifies the public API surface introduced by Epic 29 (Claude Code Skill/Subagent Compatibility): the low-level primitives that let Claude Code workflow skills run with minimal rewriting. This is a pure verification example: no API key is required, so it can run in CI as both documentation and regression coverage.
swift run ClaudeCodeCompatExample
No API key required — all checks are synchronous, pure-function calls against the public SDK surface.
What you'll learn (covering all 7 Epic 29 stories):
- Story 29.1 —
createTaskTool()is a Claude Code-compatible alias ofcreateAgentTool()with shared schema, required fields, and launcher fields - Story 29.2 —
Agent/Tasklauncher detection contract and child tool-pool stripping to avoid recursive spawning - Story 29.3 —
Skill.baseDir/Skill.supportingFilespackage context for filesystem skills vs programmatic skills - Story 29.4 — lossless
ToolDeclarationmodel for MCP namespaced names, permission patterns (Bash(git diff:*)), and unknown/custom names that never collapse to unrestricted - Story 29.5 — shared
filterToolsByDeclarationsfiltering for skills and subagents, with diagnostics that never silently widen access - Story 29.6 —
SubAgentFieldDiagnosticsfor deferred fields (run_in_background,resume,isolation,team_name,skills, MCP references) - Story 29.7 — wiring guidance for registering the
Taskalias soTask(...)snippets can run without prompt rewrites
Key code:
// Register Task for Claude Code workflow skills; it shares schema with Agent.
let tools = getAllBaseTools(tier: .core) + [createTaskTool()]
// Lossless ToolDeclaration preserves MCP/custom/unknown names and patterns.
let decl = ToolDeclaration.parse("mcp__github__list_prs") // .recognizedMCP
let pattern = ToolDeclaration.parse("Bash(git diff:*)") // base="bash", pattern="git diff:*"
// Shared filtering exposes missing tools as diagnostics instead of widening access.
let (kept, diags) = filterToolsByDeclarations(
available: tools, allowed: ToolDeclaration.fromToolNames(["Read", "Grep"]), disallowed: nil
)
// diags.unmatchedDeclarations lists tools that were declared but unavailable.
Example Dependencies
| Example | Requires MCP dependency | Extra setup |
|---|---|---|
| BasicAgent | No | None |
| StreamingAgent | No | None |
| CustomTools | No | None |
| CustomSystemPrompt | No | None |
| PromptAPIExample | No | None |
| MultiToolExample | No | None |
| SubagentExample | No | None |
| PermissionsExample | No | None |
| MCPIntegration | Yes (import MCP) | None |
| AdvancedMCPExample | Yes (import MCP) | None |
| SessionsAndHooks | No | None |
| SkillsExample | No | None |
| SandboxExample | No | None |
| LoggerExample | No | None |
| ModelSwitchingExample | No | None |
| QueryAbortExample | No | None |
| ContextInjectionExample | No | None |
| MultiTurnExample | No | None |
| OpenAICompatExample | No | None |
| PolyvLiveExample | No | Skill directory with SKILL.md |
| CompatCoreQuery | No | None |
| CompatToolSystem | No | None |
| CompatMessageTypes | No | None |
| CompatHooks | No | None |
| CompatMCP | No | None |
| CompatSessions | No | None |
| CompatQueryMethods | No | None |
| CompatOptions | No | None |
| CompatPermissions | No | None |
| CompatSubagents | No | None |
| CompatThinkingModel | No | None |
| CompatSandbox | No | None |
| EventBusExample | No | None (synthetic events) |
| SSEBridgeExample | No | API key required |
| SkillWriterExample | No | None (local files) |
| ReviewOrchestratorExample | No | None (config only) |
| EnvInjectionExample | No | API key required |
| MessageSummaryExample | No | API key required |
| ClaudeCodeCompatExample | No | None (pure verification) |
All examples are defined as executable targets in Package.swift — no additional configuration needed.
Core Scenario Quick Index
Five essential scenarios every developer should understand. Each links to the relevant example(s):
| # | Core Scenario | Example(s) | Quick Run |
|---|---|---|---|
| 1 | Basic Agent — create, prompt, stream | BasicAgent/, StreamingAgent/ | swift run BasicAgent |
| 2 | Custom Tools — defineTool, Codable input | CustomTools/, MultiToolExample/ | swift run CustomTools |
| 3 | MCP Integration — external tool servers | MCPIntegration/, AdvancedMCPExample/, AgentMCPServerExample/ | swift run MCPIntegration |
| 4 | Session Management — save, load, fork | CompatSessions/, SessionsAndHooks/, MultiTurnExample/ | swift run SessionsAndHooks |
| 5 | Memory (Cross-Task Learning) — store, query, domain-based | MemoryStoreExample/ | swift run MemoryStoreExample |
| 6 | Self-Evolution — experience extraction, skill evolution, curation | SelfEvolutionExample/ | swift run SelfEvolutionExample |
| 7 | Runtime Events — EventBus, typed events, SSE bridge | EventBusExample/, SSEBridgeExample/ | swift run EventBusExample |
| 8 | Skill Persistence — SkillWriter, SKILL.md files | SkillWriterExample/ | swift run SkillWriterExample |
| 9 | Review Pipeline — ReviewOrchestrator, promptSuffix, additional tools | ReviewOrchestratorExample/ | swift run ReviewOrchestratorExample |
| 10 | Env Injection — AgentOptions.env, ToolContext.env | EnvInjectionExample/ | swift run EnvInjectionExample |
| 11 | Claude Code Compat (Epic 29) — Task alias, ToolDeclaration model, shared filtering, deferred-field diagnostics | ClaudeCodeCompatExample/ | swift run ClaudeCodeCompatExample |
Tip: Start with scenario 1 (BasicAgent), then explore each scenario in order. The path below covers 38 tutorial sections across 47 runnable example targets.
Recommended Learning Path
BasicAgent → StreamingAgent → CustomTools → CustomSystemPromptExample
→ PromptAPIExample → MultiToolExample → SubagentExample
→ PermissionsExample → MCPIntegration → AdvancedMCPExample
→ SessionsAndHooks → SkillsExample → SandboxExample
→ LoggerExample → ModelSwitchingExample → QueryAbortExample
→ ContextInjectionExample → MultiTurnExample → OpenAICompatExample
→ PolyvLiveExample → EventBusExample → SSEBridgeExample
→ SkillWriterExample → ReviewOrchestratorExample
→ EnvInjectionExample → MessageSummaryExample
→ ClaudeCodeCompatExample
- Start here: BasicAgent, StreamingAgent — understand the core prompt/stream APIs
- Add tools: CustomTools, CustomSystemPromptExample — learn tool definition and prompt customization
- Use built-in tools: PromptAPIExample, MultiToolExample — see agents autonomously use tools
- Multi-agent: SubagentExample — delegate tasks to sub-agents
- Security: PermissionsExample — control what tools agents can use
- MCP integration: MCPIntegration, AdvancedMCPExample — connect external tool servers
- Persistence: SessionsAndHooks — save sessions and hook into lifecycle events
- Skills: SkillsExample, PolyvLiveExample — register and execute built-in/custom skills, use SKILL.md auto-discovery
- Sandbox & Logging: SandboxExample, LoggerExample — restrict operations and capture logs
- Advanced controls: ModelSwitchingExample, QueryAbortExample — runtime model switching and query cancellation
- Context & multi-turn: ContextInjectionExample, MultiTurnExample — file caching, context injection, multi-turn conversations
- OpenAI compat: OpenAICompatExample — use DeepSeek, Qwen, Ollama, and other OpenAI-compatible APIs
- HTTP API Server: AgentHTTPServerExample — expose an Agent as a REST + SSE HTTP service
- SDK compat verification: Compat* examples — verify TypeScript SDK API parity (for SDK contributors)
- Runtime events: EventBusExample, SSEBridgeExample — EventBus publish/subscribe, SSE bridge pipeline, token streaming
- Skill persistence & review: SkillWriterExample, ReviewOrchestratorExample — persist skills to disk, configure review scheduling
- Env injection & message summaries: EnvInjectionExample, MessageSummaryExample — inject env vars, observe LLM request summaries
- Claude Code compat (Epic 29): ClaudeCodeCompatExample —
Taskalias, losslessToolDeclarationmodel, shared filtering, deferred-field diagnostics
Troubleshooting
Build errors
# Clean and rebuild
swift package clean
swift build
"No such module 'OpenAgentSDK'"
Make sure you're running from the project root directory where Package.swift is located.
API key errors
Check that your environment variable is set:
echo $ANTHROPIC_API_KEY # should print your key
# or
echo $CODEANY_API_KEY
Running in Xcode
open Package.swift
Then select any example target from the scheme selector and press Cmd+R to run.
Using GLM / Other Compatible Providers
Most examples read provider settings from environment variables, so you do not need to edit source code.
For OpenAI-compatible providers:
export CODEANY_API_KEY=your-key
export CODEANY_BASE_URL=https://open.bigmodel.cn/api/coding/paas/v4
export CODEANY_MODEL=glm-5.1
swift run BasicAgent
For Anthropic-compatible custom endpoints:
export ANTHROPIC_API_KEY=your-key
export ANTHROPIC_BASE_URL=https://open.bigmodel.cn/api/anthropic
export ANTHROPIC_MODEL=glm-5.2
swift run BasicAgent