Skip to content

Commit 3609e45

Browse files
committed
docs: add comprehensive DocC documentation to agent and web search features
- Added full DocC documentation to all public types in Agent/ and WebSearch/ - Documented OllamaAgent, AgentConfiguration, AgentEvent - Documented OllamaWebSearchClient and all web search models - Added overview sections, examples, parameters, and cross-references - Documentation quality now matches existing SDK standards
1 parent 0d10ed8 commit 3609e45

File tree

5 files changed

+341
-9
lines changed

5 files changed

+341
-9
lines changed

Sources/Swollama/Agent/AgentConfiguration.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,57 @@
11
import Foundation
22

3-
3+
/// Configuration settings for agent behavior and capabilities.
4+
///
5+
/// Controls how the agent operates during autonomous workflows, including iteration limits,
6+
/// result truncation, thinking mode, and model parameters.
7+
///
8+
/// ## Overview
9+
///
10+
/// The configuration allows you to balance between thoroughness and speed:
11+
/// - ``default``: Balanced settings suitable for most use cases
12+
/// - ``extended``: More iterations and larger context for complex tasks
13+
/// - ``fast``: Fewer iterations and disabled thinking for quick answers
14+
///
15+
/// ## Example
16+
///
17+
/// ```swift
18+
/// let config = AgentConfiguration(
19+
/// maxIterations: 15,
20+
/// truncateResults: 10000,
21+
/// enableThinking: true,
22+
/// modelOptions: ModelOptions(temperature: 0.3)
23+
/// )
24+
///
25+
/// let agent = OllamaAgent(webSearchAPIKey: apiKey, configuration: config)
26+
/// ```
427
public struct AgentConfiguration: Sendable {
28+
/// Maximum number of tool-calling iterations before the agent stops.
29+
///
30+
/// Prevents infinite loops while allowing the agent to perform multiple tool calls.
531
public let maxIterations: Int
632

33+
/// Maximum character length for tool results before truncation.
34+
///
35+
/// Set to `nil` to disable truncation. Truncation helps manage context window size.
736
public let truncateResults: Int?
837

38+
/// Whether to enable extended thinking mode for reasoning models.
39+
///
40+
/// When enabled, the model shows its reasoning process through ``AgentEvent/thinking(_:)`` events.
941
public let enableThinking: Bool
1042

43+
/// Model-specific parameters to use for all chat requests.
44+
///
45+
/// See ``ModelOptions`` for available settings like temperature, context size, etc.
1146
public let modelOptions: ModelOptions?
1247

48+
/// Creates an agent configuration with custom settings.
49+
///
50+
/// - Parameters:
51+
/// - maxIterations: Maximum tool-calling iterations (default: 10).
52+
/// - truncateResults: Maximum characters for tool results, or `nil` for no limit (default: 8000).
53+
/// - enableThinking: Enable extended thinking mode (default: true).
54+
/// - modelOptions: Optional model-specific parameters.
1355
public init(
1456
maxIterations: Int = 10,
1557
truncateResults: Int? = 8000,
@@ -22,15 +64,33 @@ public struct AgentConfiguration: Sendable {
2264
self.modelOptions = modelOptions
2365
}
2466

67+
/// Default configuration with balanced settings.
68+
///
69+
/// - Max iterations: 10
70+
/// - Truncate results: 8000 characters
71+
/// - Thinking enabled: Yes
72+
/// - Model options: None
2573
public static let `default` = AgentConfiguration()
2674

75+
/// Extended configuration for complex, multi-step tasks.
76+
///
77+
/// - Max iterations: 20
78+
/// - Truncate results: 16000 characters
79+
/// - Thinking enabled: Yes
80+
/// - Model options: Large context window (32000)
2781
public static let extended = AgentConfiguration(
2882
maxIterations: 20,
2983
truncateResults: 16000,
3084
enableThinking: true,
3185
modelOptions: ModelOptions(numCtx: 32000)
3286
)
3387

88+
/// Fast configuration for quick, simple queries.
89+
///
90+
/// - Max iterations: 5
91+
/// - Truncate results: 4000 characters
92+
/// - Thinking enabled: No
93+
/// - Model options: Low temperature (0.0) for deterministic responses
3494
public static let fast = AgentConfiguration(
3595
maxIterations: 5,
3696
truncateResults: 4000,

Sources/Swollama/Agent/AgentEvent.swift

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,64 @@
11
import Foundation
22

3-
3+
/// Events emitted during agent execution.
4+
///
5+
/// `AgentEvent` represents observable stages in an agent's workflow, allowing you to monitor
6+
/// the agent's reasoning, tool usage, and responses in real-time.
7+
///
8+
/// ## Overview
9+
///
10+
/// The agent emits events in this typical sequence:
11+
/// 1. ``thinking(_:)`` - The model's reasoning process (if enabled)
12+
/// 2. ``toolCall(name:arguments:)`` - A tool being invoked
13+
/// 3. ``toolResult(name:content:)`` - The result from the tool
14+
/// 4. Steps 1-3 repeat as needed
15+
/// 5. ``message(_:)`` - The final answer
16+
/// 6. ``done`` - Workflow complete
17+
///
18+
/// ## Example
19+
///
20+
/// ```swift
21+
/// for try await event in agent.run(prompt: "What is Swift?", model: model) {
22+
/// switch event {
23+
/// case .thinking(let text):
24+
/// print("💭 \(text)")
25+
/// case .toolCall(let name, _):
26+
/// print("🔧 Calling \(name)")
27+
/// case .toolResult(let name, let content):
28+
/// print("📊 Result from \(name)")
29+
/// case .message(let text):
30+
/// print("💬 \(text)")
31+
/// case .done:
32+
/// print("✅ Complete")
33+
/// }
34+
/// }
35+
/// ```
436
public enum AgentEvent: Sendable {
37+
/// The model's reasoning process before taking action.
38+
///
39+
/// Contains the extended thinking content from reasoning models when ``AgentConfiguration/enableThinking`` is true.
540
case thinking(String)
641

42+
/// A tool is being invoked by the model.
43+
///
44+
/// - Parameters:
45+
/// - name: The name of the tool being called (e.g., "web_search").
46+
/// - arguments: JSON string containing the tool's parameters.
747
case toolCall(name: String, arguments: String)
848

49+
/// The result returned from a tool execution.
50+
///
51+
/// - Parameters:
52+
/// - name: The name of the tool that was executed.
53+
/// - content: The result content from the tool (possibly truncated).
954
case toolResult(name: String, content: String)
1055

56+
/// The final response message from the model.
57+
///
58+
/// Contains the model's answer after completing all necessary tool calls.
1159
case message(String)
1260

61+
/// The agent workflow has completed successfully.
1362
case done
1463
}
1564

Sources/Swollama/Agent/OllamaAgent.swift

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,66 @@
11
import Foundation
22

3-
3+
/// A thread-safe autonomous agent that combines local chat models with cloud-based web search.
4+
///
5+
/// `OllamaAgent` orchestrates multi-step workflows where a language model can autonomously search
6+
/// the web, fetch pages, and synthesize information to answer complex queries. The agent operates
7+
/// in a loop, allowing the model to make multiple tool calls until it has enough information to
8+
/// provide a complete answer.
9+
///
10+
/// ## Overview
11+
///
12+
/// The agent workflow:
13+
/// 1. Sends the user's prompt to the local Ollama model
14+
/// 2. Model decides whether to call tools (web search/fetch) or answer directly
15+
/// 3. If tools are called, executes them via ``OllamaWebSearchClient``
16+
/// 4. Feeds results back to the model
17+
/// 5. Repeats until the model provides a final answer or hits iteration limit
18+
///
19+
/// All steps emit ``AgentEvent`` values through an `AsyncThrowingStream`, allowing you to observe
20+
/// the agent's reasoning, tool usage, and responses in real-time.
21+
///
22+
/// ## Example
23+
///
24+
/// ```swift
25+
/// let agent = OllamaAgent(webSearchAPIKey: "your_api_key")
26+
///
27+
/// guard let model = OllamaModelName.parse("qwen3:4b") else {
28+
/// throw OllamaError.invalidParameters("Invalid model")
29+
/// }
30+
///
31+
/// for try await event in agent.run(prompt: "What are the latest Swift features?", model: model) {
32+
/// switch event {
33+
/// case .thinking(let text):
34+
/// print("Thinking: \(text)")
35+
/// case .toolCall(let name, _):
36+
/// print("Using tool: \(name)")
37+
/// case .message(let answer):
38+
/// print("Answer: \(answer)")
39+
/// case .done:
40+
/// print("Complete")
41+
/// default:
42+
/// break
43+
/// }
44+
/// }
45+
/// ```
46+
///
47+
/// - Note: As an actor, all method calls must use `await`.
48+
/// - Important: Requires an Ollama API key for web search functionality. Get one at https://ollama.com/settings/keys
449
public actor OllamaAgent {
50+
/// The local Ollama client for chat operations.
551
public let client: OllamaClient
52+
53+
/// The cloud web search client for tool execution.
654
public let webSearch: OllamaWebSearchClient
55+
756
private let configuration: AgentConfiguration
857

58+
/// Creates a new autonomous agent.
59+
///
60+
/// - Parameters:
61+
/// - client: The local Ollama client to use. Defaults to a new ``OllamaClient`` instance.
62+
/// - webSearchAPIKey: Your Ollama API key for web search capabilities.
63+
/// - configuration: Agent behavior configuration. Defaults to ``AgentConfiguration/default``.
964
public init(
1065
client: OllamaClient = OllamaClient(),
1166
webSearchAPIKey: String,
@@ -16,6 +71,37 @@ public actor OllamaAgent {
1671
self.configuration = configuration
1772
}
1873

74+
/// Runs the agent workflow for a given prompt.
75+
///
76+
/// Executes an autonomous workflow where the model can search the web and fetch pages to gather
77+
/// information before providing an answer. The method returns immediately with an `AsyncThrowingStream`
78+
/// that emits events as the agent progresses.
79+
///
80+
/// - Parameters:
81+
/// - prompt: The user's query or instruction.
82+
/// - model: The Ollama model to use for reasoning and responses.
83+
/// - Returns: A stream of ``AgentEvent`` values representing the agent's progress.
84+
/// - Throws: Errors are thrown through the stream, including ``OllamaError/invalidParameters(_:)``
85+
/// if the agent reaches the iteration limit without completing.
86+
///
87+
/// ## Example
88+
///
89+
/// ```swift
90+
/// for try await event in agent.run(prompt: "Explain quantum computing", model: model) {
91+
/// switch event {
92+
/// case .thinking(let thought):
93+
/// print("💭 \(thought)")
94+
/// case .toolCall(let name, _):
95+
/// print("🔧 Calling \(name)")
96+
/// case .message(let answer):
97+
/// print("💬 \(answer)")
98+
/// case .done:
99+
/// print("✅ Done")
100+
/// default:
101+
/// break
102+
/// }
103+
/// }
104+
/// ```
19105
nonisolated public func run(
20106
prompt: String,
21107
model: OllamaModelName

Sources/Swollama/WebSearch/OllamaWebSearchClient.swift

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,49 @@ import Foundation
55

66
private struct InvalidResponseTypeError: Error {}
77

8-
8+
/// A thread-safe client for the Ollama cloud web search API.
9+
///
10+
/// `OllamaWebSearchClient` provides access to Ollama's cloud-based web search and web fetch capabilities,
11+
/// enabling models to search the web for current information and retrieve full page content. This is separate
12+
/// from the local ``OllamaClient`` and requires an API key for authentication.
13+
///
14+
/// ## Overview
15+
///
16+
/// The client supports two main operations:
17+
/// - Web search: Query the web for relevant pages matching a search term
18+
/// - Web fetch: Extract full content and links from a specific URL
19+
///
20+
/// ## Authentication
21+
///
22+
/// Requires an Ollama API key. Get one at: https://ollama.com/settings/keys
23+
///
24+
/// ## Example
25+
///
26+
/// ```swift
27+
/// let client = OllamaWebSearchClient(apiKey: "your_api_key")
28+
///
29+
/// let results = try await client.webSearch(query: "Swift actors", maxResults: 5)
30+
/// for result in results.results {
31+
/// print("\(result.title): \(result.url)")
32+
/// }
33+
///
34+
/// let page = try await client.webFetch(url: "https://swift.org")
35+
/// print(page.content)
36+
/// ```
37+
///
38+
/// - Note: As an actor, all method calls must use `await`.
39+
/// - Important: This client connects to Ollama's cloud API, not your local Ollama instance.
940
public actor OllamaWebSearchClient: Sendable {
1041
private let apiKey: String
1142
private let baseURL: URL
1243
private let session: URLSession
1344

45+
/// Creates a new Ollama web search client.
46+
///
47+
/// - Parameters:
48+
/// - apiKey: Your Ollama API key for authentication.
49+
/// - baseURL: The base URL for the Ollama cloud API. Defaults to `https://ollama.com`.
50+
/// - session: The URLSession to use. Defaults to `.shared`.
1451
public init(
1552
apiKey: String,
1653
baseURL: URL = URL(string: "https://ollama.com")!,
@@ -21,6 +58,15 @@ public actor OllamaWebSearchClient: Sendable {
2158
self.session = session
2259
}
2360

61+
/// Searches the web for information matching a query.
62+
///
63+
/// Returns relevant web pages with titles, URLs, and content snippets.
64+
///
65+
/// - Parameters:
66+
/// - query: The search query string.
67+
/// - maxResults: Maximum number of results to return (default 5, maximum 10).
68+
/// - Returns: A response containing an array of search results.
69+
/// - Throws: ``OllamaError/httpError(statusCode:message:)`` if the request fails.
2470
public func webSearch(
2571
query: String,
2672
maxResults: Int? = nil
@@ -29,6 +75,13 @@ public actor OllamaWebSearchClient: Sendable {
2975
return try await performRequest(path: "/api/web_search", body: request)
3076
}
3177

78+
/// Fetches the full content from a specific web page.
79+
///
80+
/// Extracts the page title, main text content, and all links found on the page.
81+
///
82+
/// - Parameter url: The complete URL of the web page to fetch.
83+
/// - Returns: A response containing the page title, content, and links.
84+
/// - Throws: ``OllamaError/httpError(statusCode:message:)`` if the request fails.
3285
public func webFetch(url: String) async throws -> WebFetchResponse {
3386
let request = WebFetchRequest(url: url)
3487
return try await performRequest(path: "/api/web_fetch", body: request)
@@ -64,6 +117,17 @@ public actor OllamaWebSearchClient: Sendable {
64117

65118

66119
extension OllamaWebSearchClient {
120+
/// Tool definition for web search function calling.
121+
///
122+
/// Provide this to ``ChatOptions/init(tools:format:modelOptions:keepAlive:think:)`` to enable
123+
/// the model to search the web for current information.
124+
///
125+
/// ## Example
126+
///
127+
/// ```swift
128+
/// let options = ChatOptions(tools: [OllamaWebSearchClient.webSearchTool])
129+
/// let response = try await client.chat(messages: messages, model: model, options: options)
130+
/// ```
67131
public static let webSearchTool = ToolDefinition(
68132
type: "function",
69133
function: FunctionDefinition(
@@ -86,6 +150,17 @@ extension OllamaWebSearchClient {
86150
)
87151
)
88152

153+
/// Tool definition for web fetch function calling.
154+
///
155+
/// Provide this to ``ChatOptions/init(tools:format:modelOptions:keepAlive:think:)`` to enable
156+
/// the model to fetch and extract full content from specific URLs.
157+
///
158+
/// ## Example
159+
///
160+
/// ```swift
161+
/// let options = ChatOptions(tools: [OllamaWebSearchClient.webFetchTool])
162+
/// let response = try await client.chat(messages: messages, model: model, options: options)
163+
/// ```
89164
public static let webFetchTool = ToolDefinition(
90165
type: "function",
91166
function: FunctionDefinition(

0 commit comments

Comments
 (0)