Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sdk Laravel Package

anthropic-ai/sdk

A PHP SDK for the Anthropic API that lets you call Claude models from Laravel or plain PHP apps, with support for streaming responses, tool use, vision inputs, and typed message building for adding AI features quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a raw SDK, not a Laravel package. There is no service provider, no config file, no facade — you write the glue. Expect to spend 30 minutes on the README and then never touch the SDK directly again.

Install and wire up:

composer require anthropic-ai/sdk
// config/services.php
'anthropic' => [
    'key' => env('ANTHROPIC_API_KEY'),
    'model' => env('ANTHROPIC_MODEL', 'claude-sonnet-4-5'),
],
// app/Providers/AppServiceProvider.php
$this->app->singleton(\Anthropic\Client::class, fn () => new \Anthropic\Client(
    apiKey: config('services.anthropic.key'),
));

First call worth shipping — a summarizer or classifier behind a route or command:

$message = app(\Anthropic\Client::class)->messages->create(
    maxTokens: 1024,
    messages: [['role' => 'user', 'content' => $prompt]],
    model: config('services.anthropic.model'),
    system: 'You are a terse summarizer.',
);

return $message->content[0]->text;

Where to look first: the README's messages->create and messages->stream examples, then src/Resources/Messages.php for the full parameter surface (tool use, system, temperature, stop_sequences, metadata). Skim src/Core/Exceptions/ — you will need APIStatusException and its subclasses (RateLimitException, AuthenticationException) for sane error handling.

Note the SDK uses named arguments throughout (Stainless-generated style). Positional args will not work and will produce confusing errors.

Implementation Patterns

Wrap it in your own service. Almost every real Laravel codebase ends up with an App\Services\Claude or ClaudeClient interface. Bind the SDK client as a singleton, but inject your wrapper into controllers and jobs — this is what makes the thing testable and lets you swap models or add caching later.

final class Claude
{
    public function __construct(private \Anthropic\Client $client) {}

    public function ask(string $prompt, array $messages = [], ?string $system = null): string
    {
        $response = $this->client->messages->create(
            maxTokens: 2048,
            messages: [...$messages, ['role' => 'user', 'content' => $prompt]],
            model: config('services.anthropic.model'),
            system: $system,
        );

        return collect($response->content)
            ->where('type', 'text')
            ->pluck('text')
            ->implode('');
    }
}

Conversation memory. The API is stateless. Persist the message array (JSON column or a messages table) and replay it. Trim or summarize old turns once you approach the context window — there is no server-side thread object to lean on.

Streaming to a browser. Use a StreamedResponse and iterate the SDK's stream object. This is the highest-value integration point for chat UIs:

return response()->stream(function () use ($prompt) {
    $stream = app(\Anthropic\Client::class)->messages->stream(
        maxTokens: 2048,
        messages: [['role' => 'user', 'content' => $prompt]],
        model: config('services.anthropic.model'),
    );

    foreach ($stream as $event) {
        if (($event->type ?? null) === 'content_block_delta') {
            echo 'data: ' . json_encode(['text' => $event->delta->text]) . "\n\n";
            @ob_flush(); flush();
        }
    }
    echo "data: [DONE]\n\n";
}, 200, [
    'Content-Type' => 'text/event-stream',
    'X-Accel-Buffering' => 'no',
    'Cache-Control' => 'no-cache',
]);

Long generations belong in a queue. Anything over ~10 seconds should be a job that writes the result to a model/table and broadcasts a MessageCompleted event over Reverb/Pusher. Queue workers also give you natural rate-limit smoothing when you cap --max-jobs or use RateLimited job middleware.

Structured output. There is no response_format: json_object. Two reliable approaches: (a) define a tool with an input schema and force tool_choice, then read $response->content[0]->input; or (b) prefill the assistant turn with { and instruct JSON-only. Validate the result with a FormRequest or Validator::make() before trusting it.

Tool use loop. For agentic features, loop until stop_reason !== 'tool_use', dispatching your own handlers for each tool_use block and appending a tool_result user turn. Keep a hard iteration cap — a bug in your handler becomes an infinite billable loop otherwise.

Caching. Wrap your Claude service with Cache::remember() keyed on hash('sha256', $system . $prompt . $model . $temperature) for deterministic prompts (classification, extraction, summarization of immutable documents). Skip caching for chat.

Gotchas and Tips

  • maxTokens is required. Omitting it is the single most common first-run error. Pick a default in config and always pass it.
  • content is an array of blocks, not a string. $message->content[0]->text breaks the moment tool use or thinking blocks appear. Always filter by type === 'text'.
  • Check stop_reason. max_tokens means your output was truncated and is probably invalid JSON or a cut-off sentence. Surface this rather than silently storing garbage.
  • Timeouts. The underlying Guzzle/PSR-18 client defaults are fine for short calls but too tight for large maxTokens values. Set a longer timeout via the client's request options or per-call options, and make sure PHP's max_execution_time and your web server's fastcgi_read_timeout agree — otherwise streaming dies mid-sentence with no error in the logs.
  • Http::fake() does nothing here. The SDK does not use Laravel's HTTP client. Fake at your own boundary: bind a fake Claude implementation in the container in tests, or check whether the SDK version ships a mock transport and use that. This is the main reason to keep the wrapper interface.
  • Retries stack. The SDK retries 429/5xx with backoff. If you also set $tries = 5 on the job you can multiply latency and cost. Pick one layer — usually SDK retries for transient errors, queue retries only for your own failures.
  • Rate limits are per-org and per-model. RateLimitException carries retry-after headers; log them. When running parallel queue workers, add Illuminate\Queue\Middleware\RateLimited keyed to your tier rather than discovering throttling at 3 a.m.
  • Model names drift. Hardcoding claude-3-5-sonnet-20241022 in five places guarantees a bad afternoon. Put it in config/services.php under one key.
  • No service provider means no config publishing, no auto-discovery. Everything above is yours to maintain. That is the trade-off for a 191-star, dependency-free SDK — you get the raw API surface with no Laravel opinions, and zero lock-in to a third party's abstraction.
  • Log every call with token counts. $response->usage->inputTokens / outputTokens — attribute them to a feature or tenant. Cost surprises show up late otherwise, and retrofitting attribution after the fact is painful.
  • Extension points are thin. No middleware pipeline like Saloon. If you need request logging, redaction, or per-tenant API keys, do it in your wrapper or a decorator around the Client — not inside the SDK.
  • Zero dependents and a small community means fewer Stack Overflow answers. Budget for reading the SDK source when behaviour surprises you; it is small and readable.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource