Skip to content

Add Anthropic (Claude) backend for AI action generation #66

Description

@NakaokaRei

Summary

Add an AnthropicBackend that uses the Claude API to convert natural language prompts into automation actions, following the same pattern as the existing OpenAIBackend.

Approach

Raw URLSession (No New Dependency)

There is no official Anthropic Swift SDK. Rather than adding a community-maintained third-party package, use raw URLSession to call the Claude Messages API (POST /v1/messages). This keeps Package.swift unchanged and avoids maintenance/compatibility risk with Swift 6.2 / macOS 26.

Structured Output via Tool Use

Claude doesn't have OpenAI-style "Structured Outputs". Instead, use tool use with forced tool choice:

  • Define an execute_actions tool with the same flat-object JSON schema used by OpenAIBackend
  • Set tool_choice: {"type": "tool", "name": "execute_actions"} to guarantee structured JSON output
  • Extract the tool call's input and decode as ActionsWrapper[BasicAction][Action]

Default Model

claude-haiku-4-5-20251001 — fast and cost-effective for this structured output task. Users can override via the model parameter.

Implementation

New file: Sources/SwiftAutoGUI/AnthropicBackend.swift

  • AnthropicBackend: ActionGenerating, Sendable struct
  • Properties: apiKey, model (configurable), baseURL (for testability/proxy)
  • Private Codable types for HTTP request/response
  • Same system prompt as OpenAIBackend
  • HTTP headers: x-api-key, anthropic-version: 2023-06-01, content-type: application/json
  • Error handling for HTTP status codes (401, 429, 5xx)

Modified files

  • ActionGenerator.swift — Add init(anthropicKey:model:) convenience initializer
  • ActionGenerating.swift — Update doc comments to list AnthropicBackend
  • ActionGeneratorTests.swift — Add availability tests, convenience init test, and tool_use response JSON parsing tests
  • CLAUDE.md — Add AnthropicBackend.swift to AI Action Generation section

No changes needed

  • Package.swift — No new dependencies (URLSession only)

Usage

// With default model (claude-haiku-4-5-20251001)
let generator = ActionGenerator(anthropicKey: "sk-ant-...")
let actions = try await generator.generateActionSequence(from: "click at 100, 200")
await actions.execute()

// With custom model
let backend = AnthropicBackend(apiKey: "sk-ant-...", model: "claude-sonnet-4-6-20250514")
let generator = ActionGenerator(backend: backend)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions