### Setup Development Prerequisites Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Install SwiftLint, a dependency for code linting, using the provided make command. This ensures your development environment is properly configured. ```bash make setup ``` -------------------------------- ### Initialize Agent with Anthropic Provider Source: https://github.com/fbeeper/agentkitten/blob/main/README.md Sets up a basic AgentKitten agent using the Anthropic inference provider and a custom search tool. This is a starting point for creating conversational agents. ```swift import AgentKitten import AgentKittenAnthropicInference let provider = InferenceProvider.anthropic() let toolDefinition = ToolDefinition(tools: [ AnyAgentTool(MySearchTool()), ]) let behavior = AgentBehavior( systemPrompt: "You are a search assistant.", defaultAutomaticCompactionPolicy: .enabled( trigger: .percentOfContextWindow(0.5) ) ) let agent = Agent( provider: provider, behavior: behavior, toolDefinition: toolDefinition ) let session = agent.makeSession() ``` -------------------------------- ### Run Agent Conversation Turn Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/GettingStarted.md Initiate a session, send a message, and stream the response events from the agent. This example demonstrates handling text deltas and the final result. ```swift let session = agent.makeSession() let turn = try await session.send("Summarize the Swift memory model.") for try await event in turn.events { switch event.kind { case .textDelta(let chunk): print(chunk, terminator: "") case .result(let assistant): // Final assembled message, if you didn't care about the stream the deltas. _ = assistant.text default: break } } ``` -------------------------------- ### Default Structured Output Instruction Format Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide03.md Defines the default instruction format used to guide the OpenAI model towards generating a single, valid JSON value conforming to a given schema. This format explicitly prohibits markdown, code blocks, or backticks in the output. ```swift public static let defaultStructuredOutputInstructionFormat = """ Respond with a single valid JSON value that conforms to this schema: %@ Output only the raw JSON value. Do not use markdown, code blocks, or backticks. ...""" ``` -------------------------------- ### Example JSON Outcome Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide03.md A sample JSON object representing a successful outcome, often used in testing or demonstrating structured data. ```json { "status": true, "outcome": "A provider that also supports structured inference output." } ``` -------------------------------- ### Create an Agent with Search Tool Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/AgentKitten.md Sets up an AgentKitten agent with a specific inference provider and a search tool, enabling automatic context window compaction. ```swift import AgentKitten import AgentKittenAnthropicInference let provider = InferenceProvider.anthropic() let toolDefinition = ToolDefinition(tools: [ AnyAgentTool(MySearchTool()), ]) let behavior = AgentBehavior( systemPrompt: "You are a search assistant.", defaultAutomaticCompactionPolicy: . enabled( trigger: .percentOfContextWindow(0.5) ) ) let agent = Agent( provider: provider, behavior: behavior, toolDefinition: toolDefinition, ) let session = agent.makeSession() ``` -------------------------------- ### Build the Project Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Compile the AgentKitten project using the make build command. This ensures the code is free of compilation errors. ```bash make build ``` -------------------------------- ### Clone AgentKitten Repository Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Clone the AgentKitten repository and navigate into the project directory. This is the first step for setting up your development environment. ```bash git clone https://github.com/fbeeper/agentkitten.git cd agentkitten ``` -------------------------------- ### Run Project Tests Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Execute the test suite for AgentKitten using the make test command. This verifies the correctness of the codebase. ```bash make test ``` -------------------------------- ### Define Agent with System Prompt Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/GettingStarted.md Create an Agent instance by pairing an inference provider with an AgentBehavior that includes a system prompt. ```swift let agent = Agent( provider: provider, behavior: AgentBehavior( systemPrompt: "You are a concise, helpful assistant." ), ) ``` -------------------------------- ### Run All Development Checks Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Execute all development checks, including linting, building, and testing, by running the make all command. This is a comprehensive check before submitting changes. ```bash make all ``` -------------------------------- ### Lint Code with SwiftLint Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md Run the linting process using the make lint command. This checks your code for style and quality issues. ```bash make lint ``` -------------------------------- ### Source File Header Source: https://github.com/fbeeper/agentkitten/blob/main/CONTRIBUTING.md All owned Swift source files in `Sources/` and `Tests/` must begin with this SPDX header. Ensure compliance with licensing and copyright information. ```swift // SPDX-FileCopyrightText: 2026 AgentKitten Authors and Contributors // SPDX-License-Identifier: Apache-2.0 ``` -------------------------------- ### Initialize Anthropic Inference Provider Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/GettingStarted.md Instantiate the Anthropic inference provider. It reads the API key from the ANTHROPIC_API_KEY environment variable by default. ```swift import AgentKittenAnthropicInference let provider = InferenceProvider.anthropic() ``` -------------------------------- ### Add AgentKitten to Package.swift Source: https://github.com/fbeeper/agentkitten/blob/main/README.md Add this line to your Package.swift file to include the AgentKitten package. Ensure you are using a compatible Swift version. ```swift .package(url: "https://github.com/fbeeper/agentkitten", from: "0.0.6") ``` -------------------------------- ### Add AgentKitten Products to Target Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/GettingStarted.md Include the AgentKitten umbrella product and an inference provider in your application's target. ```swift .target( name: "MyApp", dependencies: [ .product(name: "AgentKitten", package: "agentkitten"), .product(name: "AgentKittenAnthropicInference", package: "agentkitten"), ], ) ``` -------------------------------- ### Conform OpenAIInferenceSession to ContextCompactableSession Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide05.md Implement the `compactionEntries` and `applyCompaction` methods to enable context compaction. The `compactionEntries` method renders the session history, and `applyCompaction` applies the compaction logic. ```swift extension OpenAIInferenceSession: ContextCompactableSession { public func compactionEntries() -> [RenderedSessionEntry] { history.map { RenderedSessionEntry(isTurnStart: $0.role == .user, rendered: render($0)) } } public func applyCompaction(summary: String?, preservedRecentTurnCount: Int) async throws -> ContextCompactionResult { /* ... */ } } ``` -------------------------------- ### Switch Inference Provider Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/AgentKitten.md Illustrates how to change the inference provider for an AgentKitten agent from Anthropic to OpenAI. ```diff - import AgentKittenAnthropicInference + import AgentKittenOpenAIInference - let provider = InferenceProvider.anthropic() + let provider = InferenceProvider.openAI() ``` -------------------------------- ### Public Factory Methods for OpenAIInferenceProvider Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide01.md Provides ergonomic static factory methods on InferenceProvider to create instances of OpenAIInferenceProvider, simplifying its usage. ```swift extension InferenceProvider where Provider == OpenAIInferenceProvider { public static func openAI(model: String = "gpt-4o") -> Self { /* ... */ } public static func openAI(credentials: some APIKeyProviding, model: String = "gpt-4o", baseURL: URL = OpenAIInferenceProvider.defaultBaseURL) -> Self { /* ... */ } } ``` -------------------------------- ### OpenAIInferenceSession Run Method Implementation Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide01.md Implements the run method for OpenAIInferenceSession, managing operation leases, task cancellation, and stream termination to adhere to framework invariants. ```swift public func run(_ message: UserMessage, parameters: InferenceRequestParameters) async throws -> InferenceStream { let lease = try operationGate.begin(.run) let (stream, continuation) = InferenceStream.makeStream() let task = Task { await runTurn(/* ... */, continuation: continuation) } continuation.onTermination = { _ in lease.end() task.cancel() } return stream } ``` -------------------------------- ### Apply Context Compaction Logic Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide05.md This code snippet demonstrates how to apply context compaction by preserving recent turns and optionally prepending a summary. It also resets the cached token count to ensure accurate context usage calculation after compaction. ```swift let plan = TurnPreservationPlan(entries: history, preservedRecentTurnCount: preservedRecentTurnCount, isTurnStart: { $0.role == .user }) history = summary.map { summaryMessages($0) + plan.recentEntries(from: history) } ?? plan.recentEntries(from: history) cachedContextTokens = .unknown ``` -------------------------------- ### Implement StructuredInferenceSession for OpenAI Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide03.md Conform your OpenAI inference session to `StructuredInferenceSession` by implementing the `generateStream` method. This involves building a structured system prompt, running the agentic loop, and decoding the JSON output according to the provided schema. ```swift extension OpenAIInferenceSession: StructuredInferenceSession { public func generateStream( prompt: String, parameters: InferenceRequestParameters, ) async throws -> StructuredInferenceStream { let system = buildStructuredSystemPrompt(schemaJSON: encodeStructuredSchema(T.jsonSchema)) // run the same agentic loop as a text turn (tools allowed), then: let value = try decodeStructuredValue(T.self, from: outcome.text) // yield .result(value, ...) } } ``` -------------------------------- ### Obtain Text Output from Agent Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/AgentKitten.md Sends a message to an AgentKitten session and iterates through events to print text responses. ```swift let turn = try await session.send("Find me parks near downtown.") for try await event in turn.events { if case .textDelta(let text) = event.kind { print(text, terminator: "") } } ``` -------------------------------- ### Convert Agent Tool to OpenAI Tool Schema Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide02.md Converts a registered `AnyAgentTool` to the provider's tool schema, injecting the expected rationale field. This is done once at initialization. ```swift static func openAITool(from tool: AnyAgentTool, rationaleDescription: String) -> OpenAITool { OpenAITool( type: "function", function: .init( name: tool.name, description: tool.description, parameters: InferenceProviderJSONValue.injectingRationale( into: InferenceProviderJSONValue.encoding(tool.schema.parameters), description: rationaleDescription, ), ), ) } ``` -------------------------------- ### Drive the Agentic Loop with Tool Calls Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide02.md Repeats the process of preparing a round, running a request, and recording the round until the model stops asking for tools. This loop handles step budgets and tool call detection. ```swift repeat { try Task.checkCancellation() guard await toolTurnRuntime.prepareRound() else { break } // step budget let outcome = try await runSingleRequest(/* streams events, appends to turnHistory */) stopReason = outcome.stopReason hasToolCalls = outcome.hasToolCalls await toolTurnRuntime.recordRound() } while hasToolCalls ``` -------------------------------- ### Obtain Structured Output from Agent Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/AgentKitten.md Generates structured output (e.g., an array of PointOfInterest) from an AgentKitten session based on a query. ```swift let turn: Turn<[PointOfInterest]> = try await session.generate("Find me parks near downtown.") for try await event in turn.events { if case .result(let pois) = event.kind { didLoad(pois) } } ``` -------------------------------- ### Add AgentKitten Dependency Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/GettingStarted.md Add the AgentKitten package to your Swift Package Manager dependencies. ```swift dependencies: [ .package(url: "https://github.com/fbeeper/agentkitten", from: "0.0.6"), ] ``` -------------------------------- ### Determine Session Compatibility Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceSessionLifecycle.md Checks if an existing inference session can be reused or needs to be replaced based on provider changes. A provider change necessitates a replacement. ```swift public nonisolated func sessionCompatibility(from current: ..., to next: ...) -> SessionCompatibility { current.provider != next.provider ? .replace : .reuse } ``` -------------------------------- ### Define SPM Target for Inference Provider Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide.md Configure your Swift Package Manager target to depend on AgentKittenCore and AgentKittenInferenceSupport. This sets up the basic structure for your custom provider. ```swift .target( name: "AgentKittenOpenAIInference", dependencies: ["AgentKittenCore", "AgentKittenInferenceSupport"], ), ``` -------------------------------- ### Create New Inference Session with History Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceSessionLifecycle.md Constructs a new inference session, optionally carrying forward the history from a previous session. This is crucial for maintaining conversation context. ```swift public func makeSession(continuing session: OpenAIInferenceSession, ...) async throws -> OpenAIInferenceSession { let history = await session.captureHistory() return makeOpenAISession(systemPrompt: systemPrompt, toolRuntime: toolRuntime, initialHistory: history) } ``` -------------------------------- ### Emit Paired Events for Tool Execution Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide02.md Emits tool call events and delegates tool invocation to the `ToolTurnRuntime`. This ensures proper event ordering and handling of approvals and hooks. ```swift emit(.toolCallRequested(id: callID, name: call.name, argumentsJSON: argsJSON)) let outcome = await toolTurnRuntime.invoke( pending, onApprovalRequired: { emit(.toolApprovalRequired(call: $0)) }, onHookFired: { emit(.toolHookFired($0)) }, ) // ... emit(.toolCallCompleted(id: callID, name: call.name, outcome: .success(content: content))) ``` -------------------------------- ### Define SPM Test Target for Inference Provider Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide.md Set up the test target for your inference provider, ensuring it includes dependencies for testing, such as AgentKittenInferenceTestSupport for stream validation. ```swift .testTarget( name: "AgentKittenOpenAIInferenceTests", dependencies: [ "AgentKittenOpenAIInference", "AgentKittenInferenceSupport", "AgentKittenInferenceTestSupport", ], ), ``` -------------------------------- ### OpenAIInferenceProvider Actor Definition Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide01.md Defines the OpenAIInferenceProvider actor, conforming to InferenceProviding. It holds configuration and provides a factory method for creating inference sessions. ```swift public actor OpenAIInferenceProvider: InferenceProviding { public init( credentials: OpenAICredentials = .key(EnvironmentAPIKeyProvider("OPENAI_API_KEY")), model: String = "gpt-4o", baseURL: URL = OpenAIInferenceProvider.defaultBaseURL, // ... rendering + structured-output config, added in later steps ) public nonisolated func makeSession( systemPrompt: String?, toolRuntime: ToolRuntime, toolSelection: ToolSelection, inferenceContext: InferenceContext, ) -> OpenAIInferenceSession { /* ... */ } } ``` -------------------------------- ### InferenceSession Protocol Definition Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide01.md Defines the core InferenceSession protocol, including the associated Stream type for asynchronous event sequences and the run method for initiating inference. ```swift // InferenceSession.swift public typealias InferenceStream = AsyncThrowingStream, Error> public protocol InferenceSession: Actor { associatedtype Stream: AsyncSequence & Sendable where Stream.Element == InferenceEvent func run(_ message: UserMessage, parameters: InferenceRequestParameters) async throws -> Stream func contextUsage() async throws -> ContextUsage // Defaulted to throw. And we'll keep it that way until Step 4. } ``` -------------------------------- ### Override contextUsage for Token Counting Source: https://github.com/fbeeper/agentkitten/blob/main/Sources/AgentKitten/AgentKitten.docc/InferenceProviderGuide/InferenceProviderGuide04.md This Swift function overrides the default `contextUsage()` to provide custom token counting logic. It acquires an operation gate before calling `uncheckedContextUsage()`. Use this when you need to implement specific strategies for determining token usage, especially when the provider doesn't offer a direct method. ```swift public func contextUsage() async throws -> ContextUsage { let lease = try operationGate.begin(.contextUsage) defer { lease.end() } return try await uncheckedContextUsage() } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.