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

Anthropic Laravel Laravel Package

mozex/anthropic-laravel

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm your framework version before you install. As of 1.9.0 the package requires laravel/framework ^12.69|^13.30. That is not a stylistic bump: Laravel 11 went end-of-life for security fixes on March 12, 2026, and three advisories (GHSA-5vg9-5847-vvmq, GHSA-crmm-hgp2-wgrp, GHSA-jh5r-qr3c-85q8) affect every L11 release. The new floors (12.69.0 / 13.30.0) are the first versions containing all three fixes.

# On Laravel 12.69+ or 13.30+
composer require mozex/anthropic-laravel

# On Laravel 11 this silently resolves to 1.8.2 — check what you actually got
composer show mozex/anthropic-laravel

Then publish and configure:

php artisan vendor:publish --tag="anthropic-config"   # confirm tag in the service provider
ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_BASE_URL=...   # only if you proxy through a gateway

Where to look first, in order: config/anthropic.php (what is actually configurable), the package service provider (what is bound into the container and under which key), the README usage block, then the changelog for anything the README lags behind.

First use case: a single non-streaming message from php artisan tinker or a throwaway route, printing the text content blocks. Do this before wiring anything into a controller — it proves the API key, the model name, and outbound network egress (a common silent failure inside containers) in about two minutes.

$response = Anthropic::messages()->create([
    'model'      => config('anthropic.model'),
    'max_tokens' => 512,
    'messages'   => [['role' => 'user', 'content' => 'Say hello in one sentence.']],
]);

Implementation Patterns

Resolve from the container; don't new the client. Use the facade for scripts and one-offs, but constructor-inject the underlying client (or your own wrapper interface) in application code. This is the single decision that makes the rest of these patterns possible.

Put every call behind one application service. Controllers, jobs, and commands should call App\Services\Claude — not the vendor client. That class owns timeouts, retry policy, model selection, logging, and token accounting. When the SDK moves, you edit one file.

final class Claude
{
    public function __construct(private AnthropicClient $client) {}

    public function complete(string $system, array $messages, int $maxTokens = 1024): string
    {
        return retry(3, function () use ($system, $messages, $maxTokens) {
            $res = $this->client->messages()->create([
                'model'      => config('anthropic.model'),
                'system'     => $system,
                'max_tokens' => $maxTokens,
                'messages'   => $messages,
            ]);

            return collect($res['content'] ?? [])
                ->where('type', 'text')
                ->pluck('text')
                ->implode("\n");
        }, 500);
    }
}

Keep prompts out of PHP literals. Store system prompts in lang/ files, config, or dedicated prompt classes. Prompts are content and get edited far more often than code; burying them in a controller guarantees drift and makes them untestable.

Streaming belongs behind a streamed response, not a normal one. For chat UIs, return response()->stream() (or the package's stream helper) with text/event-stream, and disable output buffering. Anything that buffers — Debugbar, some middleware, nginx proxy_buffering — turns streaming back into a slow blocking request and hides the bug until production.

Tool use / function calling: loop, don't recurse. Declare tool schemas, dispatch each tool_use block to a real Laravel action or service, append tool_result blocks, and re-call until stop_reason is no longer tool_use. Put a hard iteration cap (5–8) on the loop; a model that keeps calling an erroring tool will happily burn your budget.

Structured output: validate, don't trust. Ask for JSON, then run it through Validator::make() or hydrate a DTO (spatie/laravel-data). On failure, retry once with the validation errors appended to the prompt. Never json_decode() straight into business logic.

Push anything slow or large into a queue. Requests over a few seconds should be jobs with explicit $timeout, $tries, and $backoff. Add ShouldBeUnique or a RateLimited middleware for per-user throttling — spend control is an application concern, not something the package gives you.

Testing: bind a fake implementation of your Claude interface in the container for feature tests, and unit-test prompt assembly as pure string/array assertions. If you must test one level lower, fake at the HTTP layer. No test suite should need a live key.

Gotchas and Tips

  • Laravel 11 is now a security dead end. Composer will hold you at 1.8.2, which is not a bug — it's the constraint doing its job. Do not "fix" it with --ignore-platform-reqs or by widening the package constraint; upgrade the framework to 12.69+ / 13.30+ first, then the package, then re-run your suite. The Laravel major bump will surface unrelated breaking changes (middleware, exception handling) that you want attributed correctly.
  • Version pinning in CI matters. If your CI matrix still includes L11, composer update will quietly resolve differently per job. Pin mozex/anthropic-laravel:^1.8.2 where you genuinely need L11 compatibility, and ^1.9 only on the L12.69+/L13.30+ jobs — otherwise your green build doesn't mean what you think.
  • Env vars are read at config-compile time only. config('anthropic.api_key') inside the config file is fine; env() calls sprinkled through your own code break the moment php artisan config:cache runs. This is the most common "works locally, broken in prod" failure with this class of package.
  • A missing API key fails at call time, not boot time. Add a fail-fast check (a service provider assertion or a health-check endpoint) so you learn about a bad deploy from monitoring rather than from a user's first message.
  • Retries multiply cost. Know whether the SDK retries and how many times, and whether your retry() helper stacks on top of it. A 3× SDK retry wrapped in a 3× app retry is nine billable attempts.
  • Handle 429 with backoff, not with a tight loop. Rate limits and spend limits are different failure modes; log them separately so you can tell "too fast" from "out of credit."
  • Conversation history grows unbounded. Truncate or summarise before you hit the context window. Sending the full chat log on every turn is the classic quiet cost blow-up.
  • Extension points worth knowing: swap the container binding in your own service provider (fake, proxy, or decorator), install a custom Guzzle/HTTP handler for request logging and latency metrics, and decorate rather than fork if you need cross-cutting behaviour. Bind your interface, not the vendor class, everywhere in app code.
  • The banner/icon in 1.9.0 is cosmetic. No action needed — but if you publish vendor assets, re-publish so anything referenced by the package's views resolves.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle