-
Notifications
You must be signed in to change notification settings - Fork 2
ClaudeClient
Pair\Services\ClaudeClient is a lightweight HTTP client for Anthropic's Claude Messages API.
It focuses on the integration paths Pair applications need most often:
- Messages API calls for text, tool-capable, and multimodal model responses
- stateless chat helpers that accept
user,assistant, andsystemmessage roles - text extraction from Claude content blocks
The Pair core does not require an Anthropic SDK. The client uses cURL and keeps the provider dependency optional.
CLAUDE_API_KEY=
CLAUDE_API_BASE_URL="https://api.anthropic.com/v1"
CLAUDE_MESSAGES_MODEL=claude-sonnet-4-5
CLAUDE_API_VERSION=2023-06-01
CLAUDE_MAX_TOKENS=1024
CLAUDE_TIMEOUT=30
CLAUDE_CONNECT_TIMEOUT=5Keys:
-
CLAUDE_API_KEYis required before outbound API calls. -
CLAUDE_API_BASE_URLdefaults to the Claude REST API base URL. -
CLAUDE_MESSAGES_MODELis the default model for/messages. -
CLAUDE_API_VERSIONsets the requiredanthropic-versionrequest header. -
CLAUDE_MAX_TOKENSis the default output cap when callers omitmax_tokens.
Pair v4 integrations should be registered explicitly. An application can expose Claude as the AI adapter:
use Pair\Core\AdapterKeys;
use Pair\Core\Application;
use Pair\Services\ClaudeClient;
$app = Application::getInstance();
$app->setAdapter(AdapterKeys::AI, new ClaudeClient());
$ai = $app->adapter(AdapterKeys::AI, ClaudeClient::class);This keeps Claude optional and avoids automatic package discovery.
__construct(?string $apiKey = null, ?string $apiBaseUrl = null, ?string $messagesModel = null, ?string $apiVersion = null, ?int $maxTokens = null, ?int $timeout = null, ?int $connectTimeout = null)
Creates the client with explicit values or Env defaults.
apiKeySet(): boolcreateMessage(array $messages, array $options = []): arraycreateTextMessage(array $messages, array $options = []): stringcreateTextResponse(string $input, array $options = []): stringextractText(array $response): string
Use createMessage() when the caller needs the full Claude response.
use Pair\Http\JsonResponse;
use Pair\Services\ClaudeClient;
$client = new ClaudeClient();
$response = $client->createMessage([
['role' => 'user', 'content' => 'Summarize this support ticket.'],
], [
'system' => 'Return concise Italian text.',
'max_tokens' => 300,
]);
return new JsonResponse([
'id' => $response['id'] ?? null,
'text' => ClaudeClient::extractText($response),
]);Use createTextResponse() for the common single-prompt case:
use Pair\Services\ClaudeClient;
$client = new ClaudeClient();
$summary = $client->createTextResponse('Summarize this CRM note.', [
'system' => 'Return one sentence.',
]);The Claude Messages API is stateless. Store conversation state in the Pair application and send the relevant history on each turn.
use Pair\Services\ClaudeClient;
$client = new ClaudeClient();
$answer = $client->createTextMessage([
['role' => 'system', 'content' => 'You answer in Italian.'],
['role' => 'user', 'content' => 'Ciao, chi sei?'],
]);system messages are lifted into the top-level Claude system field. user and assistant messages remain in the transcript.
Claude does not expose an Anthropic-native embedding model. Anthropic documentation recommends using Voyage AI or another embedding provider for retrieval use cases. Pair therefore keeps embeddings out of ClaudeClient.
Do not log raw prompts, uploaded files, model outputs, tool outputs, or chat transcripts by default.
Prefer logging operational metadata only:
- endpoint or feature name
- selected model
- request duration
- token usage from the API response
- project-side entity IDs such as
ticket_idordocument_id - error code and sanitized error message
- Keep
CLAUDE_API_KEYin.env, never in Git. - Keep provider-specific domain mapping in project services, not controllers.
- Store chatbot history in project-owned tables when the application needs memory.
- For semantic search, use OpenAI, Gemini, Voyage AI, or another embedding provider separately from Claude.
See also: API, Integrations, AdapterRegistry, JsonResponse, OpenAIClient, GeminiClient.