Weave Code
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

Ai Anthropic Platform Laravel Package

symfony/ai-anthropic-platform

Symfony AI integration for Anthropic’s Claude via the Anthropic Platform. Provides a PHP client and abstractions to send prompts, handle responses, and plug Claude into Symfony apps with a consistent AI interface for chat and text generation.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:
    composer require symfony/ai-anthropic-platform
    
  2. Configure API Key: Add your Anthropic API key to .env:
    ANTHROPIC_API_KEY=your_api_key_here
    
  3. Basic Usage: Register the client in config/services.yaml:
    Symfony\AI\Client\AnthropicClient:
        arguments:
            $apiKey: '%env(ANTHROPIC_API_KEY)%'
    
    Use it in a controller or service:
    use Symfony\AI\Client\AnthropicClient;
    
    class ChatController {
        public function __construct(private AnthropicClient $client) {}
    
        public function ask(string $question): string {
            $response = $this->client->chat([
                'model' => 'claude-3-haiku',
                'messages' => [
                    ['role' => 'user', 'content' => $question],
                ],
            ]);
            return $response['content'][0]['text'];
        }
    }
    

First Use Case

Build a Chatbot Endpoint:

// src/Controller/ChatController.php
use Symfony\AI\Client\AnthropicClient;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

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

    #[Route('/chat', name: 'app_chat')]
    public function __invoke(string $question): Response {
        $response = $this->client->chat([
            'model' => 'claude-3-haiku',
            'messages' => [['role' => 'user', 'content' => $question]],
        ]);
        return new Response($response['content'][0]['text']);
    }
}

Test with:

curl -X POST "http://localhost:8000/chat?question=What%20is%20Symfony%3F"

Implementation Patterns

Core Workflows

  1. Synchronous Chat:

    $response = $client->chat([
        'model' => 'claude-3-sonnet',
        'messages' => [
            ['role' => 'system', 'content' => 'You are a helpful assistant.'],
            ['role' => 'user', 'content' => 'Explain Laravel Eloquent.'],
        ],
    ]);
    // Access: $response['content'][0]['text']
    
  2. Streaming Responses: Use MultiPartResult for real-time output (e.g., chat UIs):

    $response = $client->chatStream([
        'model' => 'claude-3-haiku',
        'messages' => [['role' => 'user', 'content' => 'Tell me a joke.']],
    ]);
    
    foreach ($response as $chunk) {
        echo $chunk['content'][0]['text'];
    }
    
  3. Tool Use: Define tools and invoke them:

    $response = $client->chat([
        'model' => 'claude-3-sonnet',
        'tools' => [
            ['type' => 'function', 'name' => 'get_weather', 'description' => 'Fetch weather data.'],
        ],
        'messages' => [
            ['role' => 'user', 'content' => 'What is the weather in Paris?'],
        ],
    ]);
    // Check $response['tool_calls'] for execution details.
    
  4. Prompt Caching: Cache prompts to reduce API calls:

    $cache = new \Symfony\Component\Cache\Adapter\FilesystemAdapter();
    $cachedPrompt = $cache->get('prompt_key', function() use ($client) {
        return $client->chat([/* prompt */]);
    });
    

Integration Tips

  • Symfony Messenger: Offload async tasks (e.g., batch content generation):

    use Symfony\Component\Messenger\MessageBusInterface;
    
    class ContentGenerator {
        public function __construct(
            private AnthropicClient $client,
            private MessageBusInterface $bus
        ) {}
    
        public function generate(string $prompt) {
            $this->bus->dispatch(new GenerateContentMessage($prompt));
        }
    }
    
  • API Platform: Expose AI endpoints as REST resources:

    # config/api_platform/resources.yaml
    App\Entity\ChatResponse:
        collectionOperations:
            ask:
                method: 'POST'
                path: '/chat'
                controller: App\Controller\ChatController::ask
    
  • Mercure: Stream responses to clients:

    use Symfony\Component\Mercure\Update;
    use Symfony\Component\Mercure\HubInterface;
    
    class ChatController {
        public function __construct(private AnthropicClient $client, private HubInterface $hub) {}
    
        public function stream(string $question) {
            $response = $this->client->chatStream([/* ... */]);
            foreach ($response as $chunk) {
                $this->hub->publish(new Update('chat', $chunk['content'][0]['text']));
            }
        }
    }
    
  • Dependency Injection: Route models dynamically:

    services:
        Symfony\AI\Client\AnthropicClient:
            arguments:
                $modelRouter: '@app.model_router' # Custom service to route models
    

Gotchas and Tips

Pitfalls

  1. Tool Calls in Streaming:

    • Issue: Tool calls may drop in streaming mode (fixed in v0.8.1).
    • Fix: Use synchronous calls for tool-heavy workflows or patch the stream handler.
  2. Null Content in Normalization:

    • Issue: AssistantMessageNormalizer may return null content (bug #1670).
    • Fix: Validate responses:
      $content = $response['content'] ?? ['text' => ''];
      
  3. String Payloads:

    • Issue: Passing strings to ModelClient throws InvalidArgumentException (bug #1711).
    • Fix: Ensure payloads are arrays:
      $client->chat(['model' => 'claude-3-haiku', 'messages' => [...]]);
      
  4. Multi-Part Responses:

    • Issue: Pre-v0.8.0 may not handle MultiPartResult correctly.
    • Fix: Update to v0.8.0+ and cast responses:
      $response = $client->chatStream([...]);
      $multiPart = new \Symfony\AI\Result\MultiPartResult($response);
      

Debugging

  • Enable HTTP Logging:

    # config/packages/http_client.yaml
    http_client:
        logging: true
    

    Check logs for API errors (e.g., InvalidRequestError).

  • Validate API Keys: Test with a minimal payload first:

    $client->chat(['model' => 'claude-3-haiku', 'messages' => []]);
    
  • Rate Limits: Anthropic enforces rate limits (e.g., 3000 tokens/minute). Implement exponential backoff:

    use Symfony\Contracts\HttpClient\Exception\RateLimited;
    
    try {
        $response = $client->chat([...]);
    } catch (RateLimited $e) {
        sleep($e->getRetryAfter());
        retry();
    }
    

Extension Points

  1. Custom Clients: Extend AnthropicClient for provider-specific logic:

    class CustomAnthropicClient extends AnthropicClient {
        protected function getDefaultModel(): string {
            return 'claude-3-opus'; // Override default
        }
    }
    
  2. Model Routing: Implement ModelRouterInterface to dynamically select models:

    class ModelRouter implements ModelRouterInterface {
        public function route(array $payload): string {
            return $payload['complexity'] > 0.8 ? 'claude-3-opus' : 'claude-3-haiku';
        }
    }
    
  3. Prompt Templates: Use Symfony’s Twig for dynamic prompts:

    $template = $this->twig->createTemplate('Hello {{ name }}!');
    $prompt = $template->render(['name' => 'User']);
    
  4. Caching Strategies: Cache by prompt hash:

    $cacheKey = md5(serialize($payload));
    $cache->get($cacheKey, fn() => $client->chat($payload));
    

Configuration Quirks

  • Base URI: Override the default Anthropic endpoint:

    services:
        Symfony\AI\Client\AnthropicClient:
            arguments:
                $baseUri: 'https://custom.anthropic.com/v1'
    
  • Timeouts: Adjust HTTP client timeouts:

    http_client:
        timeout_control:
            dividers:
                connect: 30
                dns: 10
                request: 60
    
  • Environment Variables: Use env() helper for dynamic config:

    $apiKey = env
    
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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views