### Running SwiftAgentKit Examples Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/README.md This section provides bash commands to run various examples included with SwiftAgentKit. These examples showcase different functionalities such as basic networking, MCP client, A2A client, AI adapters, tool-aware adapters, and the LLM orchestrator. ```bash # Basic networking example swift run BasicExample # MCP client example swift run MCPExample # A2A client example swift run A2AExample # AI adapters example swift run AdaptersExample # Tool-aware adapters example swift run ToolAwareExample # LLM orchestrator example swift run OrchestratorExample ``` -------------------------------- ### Complete A2A Server Setup with OpenAI (Swift) Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Provides a full example of setting up an A2A server using SwiftAgentKit. It retrieves the OpenAI API key from environment variables, configures an `OpenAIAdapter`, and starts the server on a specified port. Error handling for missing API keys and server startup failures is included. ```swift import Foundation import SwiftAgentKitA2A import SwiftAgentKitAdapters @main struct MyA2AServer { static func main() async { // Get API keys from environment guard let openAIKey = ProcessInfo.processInfo.environment["OPENAI_API_KEY"], !openAIKey.isEmpty else { print("Error: OPENAI_API_KEY environment variable not set") return } // Create adapter let adapter = OpenAIAdapter( apiKey: openAIKey, model: "gpt-4o" ) // Create and start server let server = A2AServer(port: 4245, adapter: adapter) do { try await server.start() print("A2A server started on port 4245") } catch { print("Failed to start server: \(error)") } } } ``` -------------------------------- ### Swift Quick Start: A2AServer with OpenAI Adapter Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Demonstrates how to initialize an OpenAIAdapter and an A2AServer, then start the server. Requires SwiftAgentKitA2A and SwiftAgentKitAdapters. ```swift import SwiftAgentKitA2A import SwiftAgentKitAdapters // Create an OpenAI adapter let openAIAdapter = OpenAIAdapter(apiKey: "your-openai-api-key") // Create an A2A server with the adapter let server = A2AServer(port: 4245, adapter: openAIAdapter) // Start the server try await server.start() ``` -------------------------------- ### Setup A2A Client Directly Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/A2A.md Provides an example of setting up an A2A client by directly parsing A2A configuration from a JSON file. It shows how to create an A2AClient instance using server details and boot call information from the configuration. ```swift import SwiftAgentKitA2A // Load A2A configuration from a JSON file let configURL = URL(fileURLWithPath: "./a2a-config.json") let a2aConfig = try A2AConfigHelper.parseA2AConfig(fileURL: configURL) // Create a client for the first configured server let server = a2aConfig.servers.first! let bootCall = a2aConfig.serverBootCalls.first { $0.name == server.name } let client = A2AClient(server: server, bootCall: bootCall) Task { try await client.initializeA2AClient(globalEnvironment: a2aConfig.globalEnvironment) print("A2A client connected to \(server.name)!") } ``` -------------------------------- ### Swift Basic Adapter Setup (No Tools) Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Demonstrates the basic setup of an adapter using the AdapterBuilder without any specific tool integrations. It initializes an OpenAIAdapter and builds the adapter, then sets up an A2AServer. ```swift let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .build() let server = A2AServer(port: 4245, adapter: adapter) ``` -------------------------------- ### Simple Adapter Builder Setup Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Illustrates the minimal code required for a basic adapter setup using the AdapterBuilder, specifying only the LLM. ```swift let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .build() ``` -------------------------------- ### Create and Start A2A Server with OpenAI Adapter Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates how to initialize an OpenAIAdapter and then use it to create and start an A2AServer. This sets up a standardized AI endpoint using the OpenAI model. ```swift let openAIAdapter = OpenAIAdapter( apiKey: "your-key", model: "gpt-4o", systemPrompt: "You are a helpful coding assistant." ) let server = A2AServer(port: 4246, adapter: openAIAdapter) try await server.start() ``` -------------------------------- ### Basic Gemini Adapter Usage Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Shows the basic setup for a GeminiAdapter, requiring an API key and the desired model. ```swift let adapter = GeminiAdapter( apiKey: "your-gemini-api-key", model: "gemini-1.5-flash" ) ``` -------------------------------- ### Composable Adapter Builder Example Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates building a composable adapter by combining an LLM, A2A client, MCP clients, and a custom tool provider using the AdapterBuilder. ```swift let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .withA2AClient(weatherAgent) .withMCPClients(fileTools) .withToolProvider(CustomToolProvider()) .build() ``` -------------------------------- ### Swift Adapter Setup with MCP Tools Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Illustrates integrating MCP clients into the adapter. This involves initializing an MCPServerManager, booting servers, creating MCPClients, connecting them, and then configuring a GeminiAdapter with these clients. ```swift // Initialize MCP clients using the new architecture let serverManager = MCPServerManager() let serverPipes = try await serverManager.bootServers(config: mcpConfig) var mcpClients: [MCPClient] = [] for (serverName, pipes) in serverPipes { let client = MCPClient(name: serverName, version: "1.0") try await client.connect(inPipe: pipes.inPipe, outPipe: pipes.outPipe) mcpClients.append(client) } let adapter = AdapterBuilder() .withLLM(GeminiAdapter(apiKey: "your-key")) .withMCPClients(mcpClients) .build() ``` -------------------------------- ### Run ToolAwareExample Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Executes the ToolAwareExample to demonstrate the tool-aware architecture. This includes basic adapter creation, tool-aware adapter setup with custom providers, tool execution, parsing, and streaming tool support. ```bash swift run ToolAwareExample ``` -------------------------------- ### Create and Run A2A Server with SwiftAgentKit Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/A2A.md This Swift code demonstrates how to implement the AgentAdapter protocol to create a custom A2A agent. It includes handling message sending and streaming, managing task status, and producing artifacts. The example also shows how to initialize and start the A2A server. ```swift import SwiftAgentKitA2A // Implement the AgentAdapter protocol struct MyAgentAdapter: AgentAdapter { var agentName: String { "My Custom Agent" } var agentDescription: String { "A custom A2A-compliant agent that provides text generation capabilities." } var cardCapabilities: AgentCard.AgentCapabilities { .init(streaming: true, pushNotifications: false) } var skills: [AgentCard.AgentSkill] { [ .init( id: "text-generation", name: "Text Generation", description: "Generates text based on prompts", tags: ["text", "generation"] ) ] } var defaultInputModes: [String] { ["text/plain"] } var defaultOutputModes: [String] { ["text/plain"] } // New API: update the provided task in the TaskStore func handleSend(_ params: MessageSendParams, task: A2ATask, store: TaskStore) async throws { // Mark working await store.updateTaskStatus( id: task.id, status: TaskStatus(state: .working) ) // Simulate processing try await Task.sleep(for: .seconds(1)) // Produce an artifact as the result let artifact = Artifact( artifactId: UUID().uuidString, parts: [.text(text: "I processed your request: \(params.message.parts)")] ) await store.updateTaskArtifacts(id: task.id, artifacts: [artifact]) // Mark completed await store.updateTaskStatus( id: task.id, status: TaskStatus(state: .completed) ) } // New API: stream status and artifact updates; do not return a value func handleStream(_ params: MessageSendParams, task: A2ATask, store: TaskStore, eventSink: @escaping (Encodable) -> Void) async throws { // Working status let working = TaskStatus(state: .working) await store.updateTaskStatus(id: task.id, status: working) let workingEvent = TaskStatusUpdateEvent( taskId: task.id, contextId: task.contextId, kind: "status-update", status: working, final: false ) eventSink(SendStreamingMessageSuccessResponse(jsonrpc: "2.0", id: requestId, result: workingEvent)) // Stream a few artifact chunks for i in 1...3 { try await Task.sleep(for: .seconds(1)) let artifact = Artifact( artifactId: UUID().uuidString, parts: [.text(text: "Chunk #\(i)")], name: "example-artifact" ) await store.updateTaskArtifacts(id: task.id, artifacts: [artifact]) let artifactEvent = TaskArtifactUpdateEvent( taskId: task.id, contextId: task.contextId, kind: "artifact-update", artifact: artifact, append: true, lastChunk: i == 3 ) eventSink(SendStreamingMessageSuccessResponse(jsonrpc: "2.0", id: requestId, result: artifactEvent)) } // Completed status let completed = TaskStatus(state: .completed) await store.updateTaskStatus(id: task.id, status: completed) let completedEvent = TaskStatusUpdateEvent( taskId: task.id, contextId: task.contextId, kind: "status-update", status: completed, final: true ) eventSink(SendStreamingMessageSuccessResponse(jsonrpc: "2.0", id: requestId, result: completedEvent)) } } // Create and start the server let adapter = MyAgentAdapter() let server = A2AServer(port: 4245, adapter: adapter) Task { try await server.start() print("A2A server started on port 4245") } ``` -------------------------------- ### Swift GeminiAdapter Initialization Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Demonstrates initializing the GeminiAdapter for Google's Gemini API, including basic setup and advanced configuration with model selection and generation parameters. Supports multimodal inputs. ```swift import SwiftAgentKitAdapters // Basic usage let adapter = GeminiAdapter(apiKey: "your-api-key") // With custom configuration let config = GeminiAdapter.Configuration( apiKey: "your-api-key", model: "gemini-1.5-flash", maxTokens: 1000, temperature: 0.7 ) let adapter = GeminiAdapter(configuration: config) ``` -------------------------------- ### Create LLMProtocolAdapter and A2AServer Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md Demonstrates how to create an instance of LLMProtocolAdapter by wrapping a custom LLM implementation and then using it to initialize an A2AServer. This is the basic setup for integrating a custom LLM with the A2A protocol. ```swift import SwiftAgentKit import SwiftAgentKitA2A import SwiftAgentKitAdapters // Create your LLM implementation let myLLM = MyCustomLLM(model: "my-model") // Create the adapter let adapter = LLMProtocolAdapter( llm: myLLM, model: "my-model", maxTokens: 1000, temperature: 0.7, systemPrompt: "You are a helpful assistant." ) // Use with A2A server let server = A2AServer(port: 4245, adapter: adapter) try await server.start() ``` -------------------------------- ### Build Tool-Aware Adapter with Basic LLM Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Shows the basic setup for a tool-aware adapter using AdapterBuilder, specifying only the LLM component. This is useful when no specific tools or clients are needed initially. ```swift let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .build() let server = A2AServer(port: 4245, adapter: adapter) ``` -------------------------------- ### Swift Adapter Setup with Both A2A and MCP Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Demonstrates configuring an adapter to use both A2A clients and MCP clients simultaneously. This setup includes an OpenAIAdapter, an A2AClient, and multiple MCPClients. ```swift let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .withA2AClient(a2aClient) .withMCPClients(mcpClients) .build() ``` -------------------------------- ### Swift Adapter Setup with A2A Agents Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Shows how to integrate A2A agents into the adapter architecture. It initializes an A2AClient, configures an AnthropicAdapter with the client, and builds the adapter. ```swift // Initialize A2A clients let a2aClient = A2AClient(server: a2aServer) try await a2aClient.initializeA2AClient() let adapter = AdapterBuilder() .withLLM(AnthropicAdapter(apiKey: "your-key")) .withA2AClient(a2aClient) .build() ``` -------------------------------- ### Manually Create Tool-Aware Adapter Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates the manual setup of a tool-aware adapter without using the AdapterBuilder. This involves creating individual tool providers and a ToolManager, then passing them to the ToolAwareAdapter. ```swift let a2aProvider = A2AToolProvider(clients: [a2aClient]) let mcpProvider = MCPToolProvider(clients: mcpClients) let toolManager = ToolManager(providers: [a2aProvider, mcpProvider]) let adapter = ToolAwareAdapter( baseAdapter: OpenAIAdapter(apiKey: "your-key"), toolManager: toolManager ) ``` -------------------------------- ### MCPServerManager Error Handling: Server Startup Failed Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/MCP.md Illustrates error handling for MCPServerManager, demonstrating how to catch the `MCPServerManagerError.serverStartupFailed` error when a server fails to start due to an invalid command path. ```swift let serverManager = MCPServerManager() do { let invalidBootCall = MCPConfig.ServerBootCall( name: "non-existent", command: "/path/to/nonexistent/server", arguments: [], environment: .object([:]) ) let _ = try await serverManager.bootServer(bootCall: invalidBootCall) } catch MCPServerManager.MCPServerManagerError.serverStartupFailed { print("Server failed to start") } catch { print("Other error: \(error)") } ``` -------------------------------- ### Install SwiftAgentKit Adapters Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md This snippet shows how to add the SwiftAgentKitAdapters dependency to your Swift Package Manager's Package.swift file. ```swift dependencies: [ .package(url: "https://github.com/your-repo/SwiftAgentKit.git", from: "1.0.0") ], targets: [ .target( name: "YourTarget", dependencies: [ "SwiftAgentKitAdapters" ] ) ] ``` -------------------------------- ### Swift: Basic REST API GET Request Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKit.md Demonstrates how to perform a basic GET request using the RestAPIManager in Swift. It shows how to instantiate the manager, specify the URL and headers, and handle the response. ```Swift import SwiftAgentKit let apiManager = RestAPIManager() // Simple GET request let response = try await apiManager.get( url: "https://api.example.com/data", headers: ["Authorization": "Bearer token"] ) print("Response: (response)") ``` -------------------------------- ### Swift: Execute Shell Commands Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKit.md Provides an example of executing shell commands using SwiftAgentKit's Shell utility. It shows how to run a command, capture its output and exit code, and pass environment variables. ```Swift import SwiftAgentKit let shell = Shell() // Execute a simple command let result = try await shell.execute("ls -la") print("Output: (result.output)") print("Exit code: (result.exitCode)") // Execute with environment variables let envResult = try await shell.execute( "echo $API_KEY", environment: ["API_KEY": "secret-value"] ) print("Environment output: (envResult.output)") ``` -------------------------------- ### Custom LLM Implementation with LLMProtocol Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md Provides an example of how to implement the LLMProtocol interface for a custom LLM. This includes defining the model name, capabilities, and methods for sending synchronous and streaming messages. ```swift struct MyCustomLLM: LLMProtocol { let model: String let logger: Logger init(model: String) { self.model = model self.logger = Logger(label: "MyCustomLLM") } func getModelName() -> String { return model } func getCapabilities() -> [LLMCapability] { return [.completion, .tools] } func send(_ messages: [Message], config: LLMRequestConfig) async throws -> LLMResponse { // Your LLM implementation here let response = "Response from my custom LLM" return LLMResponse(content: response) } func stream(_ messages: [Message], config: LLMRequestConfig) -> AsyncThrowingStream { // Your streaming implementation here return AsyncThrowingStream { continuation in // Stream implementation } } } ``` -------------------------------- ### Implement Custom Tool Provider for AdapterBuilder Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Provides an example of creating a custom tool provider by implementing the ToolProvider protocol. This allows for custom function definitions and execution logic to be integrated with adapters. ```swift struct CustomToolProvider: ToolProvider { public var name: String { "Custom Tools" } public var availableTools: [ToolDefinition] { [ ToolDefinition( name: "custom_function", description: "A custom function that does something", type: .function ) ] } public func executeTool(_ toolCall: ToolCall) async throws -> ToolResult { if toolCall.name == "custom_function" { return ToolResult( success: true, content: "Custom function executed successfully", metadata: .object(["source": .string("custom_function")]) ) } return ToolResult( success: false, content: "", error: "Unknown tool: \(toolCall.name)" ) } } let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .withToolProvider(CustomToolProvider()) .build() ``` -------------------------------- ### Swift: Implement and Use LLMProtocolAdapter Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md This example shows a complete Swift implementation of the LLMProtocolAdapter. It includes a custom LLM struct conforming to LLMProtocol, setting up an A2A server, and handling logging. The adapter allows integration with custom LLM implementations within the SwiftAgentKit framework. ```swift import Foundation import SwiftAgentKit import SwiftAgentKitA2A import SwiftAgentKitAdapters import Logging // Custom LLM implementation struct ExampleLLM: LLMProtocol { let model: String let logger: Logger init(model: String = "example-llm") { self.model = model self.logger = Logger(label: "ExampleLLM") } func getModelName() -> String { return model } func getCapabilities() -> [LLMCapability] { return [.completion, .tools] } func send(_ messages: [Message], config: LLMRequestConfig) async throws -> LLMResponse { let lastUserMessage = messages.last { $0.role == .user }?.content ?? "Hello" let response = "Response to: '\(lastUserMessage)'" return LLMResponse( content: response, metadata: LLMMetadata( promptTokens: 10, completionTokens: response.count / 4, totalTokens: 10 + (response.count / 4), finishReason: "stop" ) ) } func stream(_ messages: [Message], config: LLMRequestConfig) -> AsyncThrowingStream { return AsyncThrowingStream { continuation in Task { let response = try await send(messages, config: config) let words = response.content.components(separatedBy: " ") for (index, word) in words.enumerated() { let isComplete = index == words.count - 1 let chunk = LLMResponse( content: word + (isComplete ? "" : " "), isComplete: isComplete ) continuation.yield(chunk) if !isComplete { try await Task.sleep(nanoseconds: 100_000_000) } } continuation.finish() } } } } // Main application @main struct ExampleApp { static func main() async throws { // Set up logging LoggingSystem.bootstrap { label in var handler = StreamLogHandler.standardOutput(label: label) handler.logLevel = .info return handler } // Create LLM and adapter let exampleLLM = ExampleLLM(model: "example-llm-v1") let adapter = LLMProtocolAdapter( llm: exampleLLM, model: "example-llm-v1", maxTokens: 1000, temperature: 0.7, systemPrompt: "You are a helpful assistant." ) // Create and start A2A server let server = A2AServer(port: 4245, adapter: adapter) try await server.start() print("Server running on http://localhost:4245") // Keep server running try await Task.sleep(nanoseconds: UInt64.max) } } ``` -------------------------------- ### Swift Package Manager Installation Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/README.md This snippet shows how to add SwiftAgentKit as a dependency to your Swift project using the Swift Package Manager. It specifies the Git repository URL and the version to use. ```swift dependencies: [ .package(url: "https://github.com/JamieScanlon/SwiftAgentKit.git", from: "0.1.3") ] ``` -------------------------------- ### Swift Custom Tool Provider Implementation Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/ToolAwareArchitecture.md Provides an example of implementing a custom ToolProvider. This involves defining the provider's name, available tools (like 'custom_function'), and the logic for executing tool calls. ```swift struct CustomToolProvider: ToolProvider { public var name: String { "Custom Tools" } public var availableTools: [ToolDefinition] { [ToolDefinition(name: "custom_function", description: "A custom function", type: .function)] } public func executeTool(_ toolCall: ToolCall) async throws -> ToolResult { // Your custom implementation } } let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .withToolProvider(CustomToolProvider()) .build() ``` -------------------------------- ### Run AdaptersExample Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Executes the AdaptersExample to demonstrate basic and custom adapter usage, including enhanced OpenAI features and multi-provider fallback strategies. ```bash swift run AdaptersExample ``` -------------------------------- ### Run ToolAwareExample Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Executes the ToolAwareExample to demonstrate setting up tool-aware adapters, A2A agent integration, MCP tool integration, custom tool providers, and builder pattern usage. ```bash swift run ToolAwareExample ``` -------------------------------- ### Basic OpenAI Adapter Usage Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates the basic initialization of an OpenAIAdapter with an API key, model, and system prompt. ```swift let adapter = OpenAIAdapter( apiKey: "your-openai-api-key", model: "gpt-4o", systemPrompt: "You are a helpful assistant." ) ``` -------------------------------- ### MCPClient Error Handling: Not Connected Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/MCP.md Provides an example of error handling for MCPClient, specifically catching the `MCPClientError.notConnected` error when attempting to call a tool on a client that has not been connected. ```swift let client = MCPClient(name: "test-client", version: "1.0.0") do { // This will throw MCPClientError.notConnected let _ = try await client.callTool("test_tool") } catch MCPClient.MCPClientError.notConnected { print("Client is not connected") } catch { print("Other error: \(error)") } ``` -------------------------------- ### Basic OpenAI Adapter Usage Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/Sources/SwiftAgentKitAdapters/README.md Demonstrates how to create an OpenAI adapter and initialize an A2AServer with it. Requires the SwiftAgentKitAdapters library. ```swift import SwiftAgentKitAdapters // Create an OpenAI adapter let openAIAdapter = OpenAIAdapter(apiKey: "your-api-key") // Create an A2A server with the adapter let server = A2AServer(port: 4245, adapter: openAIAdapter) ``` -------------------------------- ### Extensible ToolProvider Implementation Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Shows how to create an extensible tool provider by implementing the `ToolProvider` protocol for custom tool logic, such as database interactions. ```swift struct DatabaseToolProvider: ToolProvider { // Your database tool implementation } ``` -------------------------------- ### Basic SwiftAgentKit Initialization Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/README.md This Swift code shows the basic initialization of SwiftAgentKit components, including the RestAPIManager, MCPManager, and A2AManager. It also demonstrates building an AI adapter using the AdapterBuilder with an OpenAI adapter. ```swift import SwiftAgentKit import SwiftAgentKitMCP import SwiftAgentKitA2A import SwiftAgentKitAdapters // Use the modules as needed let apiManager = RestAPIManager() let mcpManager = MCPManager() let a2aManager = A2AManager() // Create AI adapters with tool capabilities let adapter = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .build() print("SwiftAgentKit initialized") ``` -------------------------------- ### Backward Compatible Adapter Initialization Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Shows that existing adapters remain functional, demonstrating the initialization of an `A2AServer` with an `OpenAIAdapter`. ```swift // This still works exactly as before let server = A2AServer(port: 4245, adapter: OpenAIAdapter(apiKey: "your-key")) ``` -------------------------------- ### Build Tool-Aware Adapter with MCP Tools Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates the integration of MCP tools into a tool-aware adapter. This involves booting MCP servers, creating MCP clients, and then adding them to the AdapterBuilder. ```swift let serverManager = MCPServerManager() let serverPipes = try await serverManager.bootServers(config: mcpConfig) var mcpClients: [MCPClient] = [] for (serverName, pipes) in serverPipes { let client = MCPClient(name: serverName, version: "1.0") try await client.connect(inPipe: pipes.inPipe, outPipe: pipes.outPipe) mcpClients.append(client) } let adapter = AdapterBuilder() .withLLM(GeminiAdapter(apiKey: "your-key")) .withMCPClients(mcpClients) .build() ``` -------------------------------- ### Conversation History Management Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md Explains that the LLMProtocolAdapter automatically manages conversation history. The example shows how subsequent messages sent to the adapter will include context from previous messages, enabling coherent conversations. ```swift // First message let message1 = A2AMessage( role: "user", parts: [.text(text: "My name is Alice")], messageId: UUID().uuidString ) // Second message (includes context from first) let message2 = A2AMessage( role: "user", parts: [.text(text: "What's my name?")], messageId: UUID().uuidString ) // The LLM will have context from the previous message ``` -------------------------------- ### Boot MCP Servers Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/MCP.md Shows how to use the MCPServerManager to boot MCP servers based on a provided configuration. It returns a dictionary of server names mapped to their communication pipes, indicating readiness for connection. ```swift // Use MCPServerManager to boot servers let serverManager = MCPServerManager() let serverPipes = try await serverManager.bootServers(config: config) // serverPipes is a dictionary: [String: (inPipe: Pipe, outPipe: Pipe)] for (serverName, pipes) in serverPipes { print("Server \(serverName) is ready for connection") } ``` -------------------------------- ### Convenience Initializer for LLMProtocolAdapter Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md Shows a simplified way to create an LLMProtocolAdapter using its convenience initializer, which takes essential parameters like the LLM implementation, model name, temperature, and system prompt. ```swift let adapter = LLMProtocolAdapter( llm: myLLM, model: "my-model", maxTokens: 1000, temperature: 0.7, systemPrompt: "You are a helpful assistant." ) ``` -------------------------------- ### Make Agent Calls with A2AManager Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/A2A.md Illustrates how to make agent calls using the A2AManager. This example demonstrates creating a `ToolCall` for a specific agent function and executing it, then processing the received messages. ```swift Task { // Create a tool call for an A2A agent let toolCall = ToolCall( name: "text_generation", arguments: [ "instructions": "Write a short story about a robot learning to paint" ], instructions: "Generate creative text based on the provided prompt" ) // Execute the agent call if let messages = try await a2aManager.agentCall(toolCall) { print("Agent call successful! Received \(messages.count) messages:") for (index, message) in messages.enumerated() { print("Message \(index + 1): \(message.content)") } } else { print("Agent call returned no messages") } } ``` -------------------------------- ### Create MCP Configuration Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/MCP.md Demonstrates how to programmatically create an MCP configuration, including server boot calls with custom commands, arguments, and environment variables. It also shows how to set global environment variables for the MCP configuration. ```swift import SwiftAgentKitMCP // Create server configuration programmatically let serverBootCall = MCPConfig.ServerBootCall( name: "example-server", command: "/usr/local/bin/example-mcp-server", arguments: ["--port", "4242"], environment: .object([ "API_KEY": .string("your-api-key"), "MODEL": .string("gpt-4") ]) ) var config = MCPConfig() config.serverBootCalls = [serverBootCall] config.globalEnvironment = .object([ "LOG_LEVEL": .string("info"), "ENVIRONMENT": .string("development") ]) ``` -------------------------------- ### Initialize and Use SwiftAgentKitOrchestrator Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/Sources/SwiftAgentKitOrchestrator/README.md Demonstrates how to initialize the SwiftAgentKitOrchestrator with an LLM and configuration, access its properties, and process a conversation. It also shows how to listen for complete messages from the message stream. ```swift import SwiftAgentKitOrchestrator import SwiftAgentKit // Create an LLM that conforms to LLMProtocol let llm: LLMProtocol = SomeLLMImplementation(logger: logger) // Create orchestrator configuration let config = OrchestratorConfig( streamingEnabled: true, mcpEnabled: true, a2aEnabled: false ) // Initialize the orchestrator with the LLM and configuration let orchestrator = SwiftAgentKitOrchestrator(llm: llm, config: config, logger: logger) // Access the underlying LLM if needed let llmInstance = orchestrator.llmProtocol // Access the configuration let orchestratorConfig = orchestrator.orchestratorConfig // Process a conversation let conversation = [ Message(id: UUID(), role: .user, content: "Hello"), Message(id: UUID(), role: .assistant, content: "Hi there!") ] // Get the message stream for complete messages let messageStream = await orchestrator.messageStream var finalConversation: [Message]? // Listen for complete messages Task { for await message in messageStream { print("Received complete message: \(message.content)") finalConversation = finalConversation ?? [] finalConversation?.append(message) } } // Process the conversation (this will publish to the streams) try await orchestrator.updateConversation(conversation, availableTools: []) // Note: The orchestrator automatically manages stream lifecycle and cleanup // Example with available tools let availableTools = [ ToolDefinition( name: "calculator", description: "A simple calculator", parameters: [ .init(name: "expression", description: "Mathematical expression", type: "string", required: true) ], type: .function ) ] let conversationWithTools = [ Message(id: UUID(), role: .user, content: "What's 2 + 2?") ] let toolConversationStream = orchestrator.updateConversation(conversationWithTools, availableTools: availableTools) ``` -------------------------------- ### Create Multi-Provider Agent Adapter in Swift Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Illustrates the creation of a multi-provider agent adapter that combines multiple AI providers like OpenAI and Anthropic for redundancy. It shows how to initialize different adapters and delegate task handling and streaming. ```swift struct MultiProviderAdapter: AgentAdapter { private let openAIAdapter: OpenAIAdapter private let anthropicAdapter: AnthropicAdapter init(openAIKey: String, anthropicKey: String) { self.openAIAdapter = OpenAIAdapter(apiKey: openAIKey) self.anthropicAdapter = AnthropicAdapter(apiKey: anthropicKey) } var agentName: String { "Multi-Provider Agent" } var agentDescription: String { "An A2A-compliant agent that provides redundancy and fallback using multiple AI providers." } var cardCapabilities: AgentCard.AgentCapabilities { .init( streaming: true, pushNotifications: false, stateTransitionHistory: true ) } var skills: [AgentCard.AgentSkill] { [ .init( id: "openai-skill", name: "OpenAI Skill", description: "Provides text generation and code generation capabilities from OpenAI.", tags: ["openai"], examples: ["Tell me about Swift."], inputModes: ["text/plain"], outputModes: ["text/plain"] ), .init( id: "anthropic-skill", name: "Anthropic Skill", description: "Provides text generation and code generation capabilities from Anthropic.", tags: ["anthropic"], examples: ["What is the capital of France?"], inputModes: ["text/plain"], outputModes: ["text/plain"] ) ] } var defaultInputModes: [String] { ["text/plain"] } var defaultOutputModes: [String] { ["text/plain"] } func handleSend(_ params: MessageSendParams, task: A2ATask, store: TaskStore) async throws { // Try OpenAI first, then Anthropic as fallback do { try await openAIAdapter.handleSend(params, task: task, store: store) } catch { try await anthropicAdapter.handleSend(params, task: task, store: store) } } func handleStream(_ params: MessageSendParams, task: A2ATask, store: TaskStore, eventSink: @escaping (Encodable) -> Void) async throws { // Delegate streaming; whichever adapter succeeds first updates the store and emits events do { try await openAIAdapter.handleStream(params, task: task, store: store, eventSink: eventSink) } catch { try await anthropicAdapter.handleStream(params, task: task, store: store, eventSink: eventSink) } } } ``` -------------------------------- ### Stream Messages from Agent Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/A2A.md Demonstrates how to stream messages from an agent using an A2AClient. This example uses `MessageSendParams` with `blocking: false` and iterates over the streamed responses, handling different result types like messages, tasks, and status updates. ```swift Task { let messageParams = MessageSendParams( message: A2AMessage( role: "user", parts: [.text(text: "Generate a long response")], messageId: UUID().uuidString ), configuration: MessageSendConfiguration( acceptedOutputModes: ["text/plain"], blocking: false ) ) for try await response in client.streamMessage(params: messageParams) { switch response.result { case .message(let message): print("Streamed message: \(message.parts)") case .task(let task): print("Task created: \(task.id)") case .taskStatusUpdate(let status): print("Status update: \(status.state)") case .taskArtifactUpdate(let artifact): print("New artifact: \(artifact.artifactId)") } } } ``` -------------------------------- ### Basic Anthropic Adapter Usage Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Illustrates the basic initialization of an AnthropicAdapter with an API key and model name. ```swift let adapter = AnthropicAdapter( apiKey: "your-anthropic-api-key", model: "claude-3-5-sonnet-20241022" ) ``` -------------------------------- ### Swift AnthropicAdapter Initialization Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Illustrates how to initialize the AnthropicAdapter with basic API key or a detailed configuration. Supports different Claude models and generation parameters. ```swift import SwiftAgentKitAdapters // Basic usage let adapter = AnthropicAdapter(apiKey: "your-api-key") // With custom configuration let config = AnthropicAdapter.Configuration( apiKey: "your-api-key", model: "claude-3-5-sonnet-20241022", maxTokens: 1000, temperature: 0.7 ) let adapter = AnthropicAdapter(configuration: config) ``` -------------------------------- ### Importing SwiftAgentKit Modules Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/README.md This code demonstrates how to import the necessary SwiftAgentKit products into your target's dependencies. You can include core modules or optional ones like A2A, MCP, and Adapters. ```swift .target( name: "YourTarget", dependencies: [ .product(name: "SwiftAgentKit", package: "SwiftAgentKit"), .product(name: "SwiftAgentKitA2A", package: "SwiftAgentKit"), // Optional .product(name: "SwiftAgentKitMCP", package: "SwiftAgentKit"), // Optional .product(name: "SwiftAgentKitAdapters", package: "SwiftAgentKit"), // Optional ] ) ``` -------------------------------- ### LLMProtocolAdapter Configuration Options Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/LLMProtocolAdapter.md Defines the configuration parameters available for the LLMProtocolAdapter, including model identifier, token limits, temperature, top-p sampling, system prompts, and additional model-specific parameters. ```swift public struct Configuration: Sendable { public let model: String // Model identifier public let maxTokens: Int? // Maximum tokens to generate public let temperature: Double? // Response randomness (0.0-2.0) public let topP: Double? // Top-p sampling parameter public let systemPrompt: String? // System prompt for the LLM public let additionalParameters: JSON? // Model-specific parameters } ``` -------------------------------- ### Flexible Adapter with Anthropic and MCP Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates flexibility by configuring an adapter with Anthropic as the LLM and web tools for MCP client integration. ```swift // Anthropic with MCP tools let adapter2 = AdapterBuilder() .withLLM(AnthropicAdapter(apiKey: "your-key")) .withMCPClients(webTools) .build() ``` -------------------------------- ### Tool-Aware Adapter with Multiple Providers Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/Sources/SwiftAgentKitAdapters/README.md Shows how to build a tool-aware adapter by combining a base LLM adapter with multiple tool providers using the AdapterBuilder. Requires SwiftAgentKitAdapters and relevant tool provider clients. ```swift import SwiftAgentKitAdapters // Create base adapter let baseAdapter = OpenAIAdapter(apiKey: "your-api-key") // Create tool providers let a2aProvider = A2AToolProvider(clients: [a2aClient]) let mcpProvider = MCPToolProvider(clients: [mcpClient]) // Build tool-aware adapter let toolAwareAdapter = AdapterBuilder() .withLLM(baseAdapter) .withToolProviders([a2aProvider, mcpProvider]) .build() ``` -------------------------------- ### Flexible Adapter with OpenAI and A2A Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Demonstrates flexibility by configuring an adapter with OpenAI as the LLM and a specialist agent for A2A integration. ```swift // OpenAI with A2A agents let adapter1 = AdapterBuilder() .withLLM(OpenAIAdapter(apiKey: "your-key")) .withA2AClient(specialistAgent) .build() ``` -------------------------------- ### Build Tool-Aware Adapter with A2A Client Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKitAdapters.md Illustrates how to construct a tool-aware adapter that integrates with A2A clients. This involves initializing an A2A client and then including it in the AdapterBuilder. ```swift let a2aClient = A2AClient(server: a2aServer) try await a2aClient.initializeA2AClient() let adapter = AdapterBuilder() .withLLM(AnthropicAdapter(apiKey: "your-key")) .withA2AClient(a2aClient) .build() ``` -------------------------------- ### Swift OpenAIAdapter Initialization Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/Adapters.md Shows basic and custom configuration for the OpenAIAdapter. Supports various OpenAI models and parameters like maxTokens and temperature. ```swift import SwiftAgentKitAdapters // Basic usage let adapter = OpenAIAdapter(apiKey: "your-api-key") // With custom configuration let config = OpenAIAdapter.Configuration( apiKey: "your-api-key", model: "gpt-4o", maxTokens: 1000, temperature: 0.7 ) let adapter = OpenAIAdapter(configuration: config) ``` -------------------------------- ### Swift: Using StreamClient Source: https://github.com/jamiescanlon/swiftagentkit/blob/main/docs/SwiftAgentKit.md Shows how to create and use a StreamClient from SwiftAgentKit to manage streaming connections. It demonstrates initiating a stream and processing data chunks. ```Swift let streamClient = StreamClient() let stream = streamClient.createStream( url: "https://api.example.com/stream", headers: ["Authorization": "Bearer token"] ) for try await chunk in stream { print("Stream chunk: (chunk)") } ```