Normandy.LLM.ClaudioAdapter (normandy v1.3.0)

View Source

Adapter for integrating Claudio (Anthropic's Claude API client) with Normandy agents.

This adapter implements the Normandy.Agents.Model protocol to enable Normandy agents to use Claude models via the Claudio library.

Features

  • Full Messages API support
  • Tool/function calling integration
  • Streaming responses (via callbacks)
  • Prompt caching support
  • Vision/multimodal inputs
  • Thinking mode configuration

Example

# Initialize Claudio client
client = %Normandy.LLM.ClaudioAdapter{
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  options: [
    timeout: 60_000,
    enable_caching: true
  ]
}

# Use with Normandy agent
agent = Normandy.Agents.BaseAgent.init(%{
  client: client,
  model: "claude-3-5-sonnet-20241022",
  temperature: 0.7
})

{agent, response} = Normandy.Agents.BaseAgent.run(agent, user_input)

Configuration

The adapter supports all Claudio client options:

  • :timeout - Request timeout in milliseconds (default: 30_000)
  • :enable_caching - Enable prompt caching (default: false)
  • :thinking_budget - Token budget for extended thinking mode
  • :base_url - Custom API base URL (for testing)

Structured Outputs

By default, this adapter uses Anthropic native constrained decoding (structured outputs) to obtain schema-valid JSON from the model without relying on the legacy parse-retry loop. The structured output path is skipped — and the legacy parse-retry path is used instead — when any of the following conditions are true:

  • The kill-switch is off: config :normandy, :structured_outputs, false (global) or client.options[:structured_outputs] = false (per-client, overrides the global setting).
  • The response schema is incompatible with constrained decoding: contains an open :map field, a non-JSON-Schema scalar type (e.g. :date, :binary, :any), or exceeds the nesting depth guard.
  • The call carries tools — a stop_reason: :tool_use response requires the legacy tool-handling loop.
  • The model returns refusal, max_tokens, or context-exceeded, or the API rejects the structured-output request — these route through the existing :on_parse_failure policy and legacy fallback.

Summary

Types

t()

@type t() :: %Normandy.LLM.ClaudioAdapter{
  __meta__: term(),
  api_key: String.t(),
  base_url: String.t() | nil,
  finch: atom() | nil,
  options: keyword()
}