Packages

Elixir client for the Anthropic Messages API — typed content blocks, native tool use, streaming, retries.

Current section

Files

Jump to
anthropic_community lib anthropic client.ex
Raw

lib/anthropic/client.ex

defmodule Anthropic.Client do
@moduledoc """
Holds connection-level configuration for the Anthropic API: credentials, base URL,
API version, retry policy, and transport pool. Built once via `new/1` and passed
explicitly as the first argument to every resource function (`Anthropic.Messages.create/2`,
`Anthropic.Models.list/1`, etc.) rather than held implicitly in process/application state.
## Resolution order for `:api_key` and `:base_url`
1. Explicit option passed to `new/1`.
2. `Application.get_env(:anthropic, key)`.
3. `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL` environment variables.
4. For `:api_key` only: raises `ArgumentError` if still unresolved. `:base_url` defaults
to `"https://api.anthropic.com"`.
"""
@derive {Inspect, except: [:api_key]}
@enforce_keys [:api_key]
defstruct [
:api_key,
base_url: "https://api.anthropic.com",
api_version: "2023-06-01",
max_retries: 2,
timeout: 600_000,
default_model: nil,
default_headers: [],
http_pool: Anthropic.HTTPTransport.Engine
]
@type t :: %__MODULE__{
api_key: String.t(),
base_url: String.t(),
api_version: String.t(),
max_retries: non_neg_integer(),
timeout: pos_integer(),
default_model: String.t() | nil,
default_headers: [{String.t(), String.t()}],
http_pool: atom()
}
@spec new(keyword()) :: t()
def new(opts \\ []) do
opts
|> Keyword.put_new_lazy(:api_key, fn -> resolve!(:api_key, "ANTHROPIC_API_KEY") end)
|> Keyword.put_new_lazy(:base_url, fn ->
resolve(:base_url, "ANTHROPIC_BASE_URL") || "https://api.anthropic.com"
end)
|> then(&struct!(__MODULE__, &1))
|> validate!()
end
defp resolve!(app_env_key, env_var) do
resolve(app_env_key, env_var) ||
raise ArgumentError,
"api_key is required (pass :api_key, set config :anthropic, :api_key, or set #{env_var})"
end
defp resolve(app_env_key, env_var) do
Application.get_env(:anthropic, app_env_key) || System.get_env(env_var)
end
defp validate!(%__MODULE__{max_retries: r}) when r < 0 do
raise ArgumentError, "max_retries must be >= 0, got: #{inspect(r)}"
end
defp validate!(%__MODULE__{api_key: key}) when not is_binary(key) or key == "" do
raise ArgumentError, "api_key must be a non-empty String.t(), got: #{inspect(key)}"
end
defp validate!(client), do: client
end