Coverage for src / infra / clients / anthropic_client.py: 14%
21 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-01-04 04:43 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-01-04 04:43 +0000
1"""Shared Anthropic client factory for mala orchestrator.
3This module provides a centralized way to create Anthropic clients with:
4- Consistent configuration from MalaConfig (api_key, base_url)
5- Automatic Braintrust wrapping for observability when available
7Usage:
8 from src.infra.clients.anthropic_client import create_anthropic_client
9 from src.infra.io.config import MalaConfig
11 config = MalaConfig.from_env()
12 client = create_anthropic_client(
13 api_key=config.llm_api_key,
14 base_url=config.llm_base_url,
15 timeout=120.0,
16 )
18 # Client is ready to use with Braintrust tracing enabled (if configured)
19 response = client.messages.create(
20 model="claude-sonnet-4-20250514",
21 max_tokens=1024,
22 messages=[{"role": "user", "content": "Hello"}],
23 )
24"""
26from __future__ import annotations
28from typing import Any
31def create_anthropic_client(
32 *,
33 api_key: str | None = None,
34 base_url: str | None = None,
35 timeout: float | None = None,
36) -> Any: # noqa: ANN401 - Return type is dynamic (Anthropic or wrapped client)
37 """Create an Anthropic client with consistent configuration and tracing.
39 This factory function centralizes Anthropic client creation to ensure:
40 1. Configuration is applied consistently (api_key, base_url)
41 2. Braintrust tracing is automatically enabled when available
42 3. Error handling and telemetry work uniformly across components
44 Args:
45 api_key: Anthropic API key. If not provided, the client will use
46 the ANTHROPIC_API_KEY environment variable.
47 base_url: Optional base URL for API requests. Use this to route
48 requests through proxies.
49 timeout: Optional timeout in seconds for API requests.
51 Returns:
52 An Anthropic client instance, optionally wrapped with Braintrust
53 tracing if available.
55 Raises:
56 RuntimeError: If the anthropic package is not installed.
58 Example:
59 from src.infra.clients.anthropic_client import create_anthropic_client
61 # Basic usage with env var for API key
62 client = create_anthropic_client()
64 # With explicit configuration
65 client = create_anthropic_client(
66 api_key="sk-...",
67 base_url="https://proxy.example.com/v1",
68 timeout=60.0,
69 )
71 # Braintrust tracing is automatic when BRAINTRUST_API_KEY is set
72 """
73 try:
74 from anthropic import Anthropic # type: ignore[import-untyped]
75 except ImportError as e:
76 raise RuntimeError(
77 "anthropic package is required. Install with: uv add anthropic"
78 ) from e
80 # Build client kwargs, only including non-None values
81 client_kwargs: dict[str, object] = {}
82 if api_key is not None:
83 client_kwargs["api_key"] = api_key
84 if base_url is not None:
85 client_kwargs["base_url"] = base_url
86 if timeout is not None:
87 client_kwargs["timeout"] = timeout
89 # Create the base client
90 client = Anthropic(**client_kwargs)
92 # Wrap with Braintrust for observability (no-op if Braintrust not configured)
93 # This provides automatic tracing of all LLM calls when BRAINTRUST_API_KEY is set
94 try:
95 from braintrust import wrap_anthropic
97 client = wrap_anthropic(client)
98 except ImportError:
99 pass # Braintrust not installed, proceed without tracing
101 return client