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

Ai Agent Laravel Package

symfony/ai-agent

Framework for building AI agents on top of Symfony AI's Platform and Store components, letting agents interact with users, perform tasks and manage workflows. Experimental, not covered by Symfony's BC promise.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Core Packages (pin to the 0.15 release train — see Gotchas):

    composer require symfony/ai-agent:^0.15 symfony/ai-platform:^0.15
    
  2. Create a Basic Agent:

    use Symfony\Component\Ai\Agent\Agent;
    use Symfony\Component\Ai\Agent\Input;
    use Symfony\Component\Ai\Agent\Output;
    
    $agent = new Agent(
        new Input('What is Laravel?'),
        new \Symfony\Component\Ai\Platform\OpenAiPlatform('your-api-key')
    );
    
    $output = $agent->run();
    echo $output->getContent();
    
  3. First Use Case: Chatbot with Wikipedia Tool

    composer require symfony/ai-wikipedia-tool:^0.15
    
    use Symfony\Component\Ai\Tool\WikipediaTool;
    
    $agent = new Agent(
        new Input('Explain Symfony AI in simple terms'),
        new \Symfony\Component\Ai\Platform\OpenAiPlatform('api-key'),
        new \Symfony\Component\Ai\Toolbox\Toolbox([new WikipediaTool()])
    );
    

Where to Look First

  • Documentation: Official guide for core concepts.
  • src/Agent.php: Entry point for agent creation.
  • src/Toolbox/: Tool integration patterns.
  • tests/: Real-world usage examples (e.g., AgentTest.php, MultiAgentTest.php).
  • CHANGELOG.md / release notes: The package is still pre-1.0 (0.15.x); check every minor bump — v0.15 removed InMemoryPlatform and reworked the mock/testing path.

Implementation Patterns

Core Workflow: Agent Lifecycle

  1. Input Processing:
    $agent->addInputProcessor(new \Symfony\Component\Ai\Agent\InputProcessor\SystemPromptInputProcessor('You are a helpful assistant.'));
    
  2. Tool Integration:
    $toolbox = new \Symfony\Component\Ai\Toolbox\Toolbox([
        new \Symfony\Component\Ai\Tool\BraveSearchTool('your-api-key'),
        new \Symfony\Component\Ai\Tool\FilesystemTool('/tmp'),
    ]);
    $agent->setToolbox($toolbox);
    
  3. Memory Management:
    $memory = new \Symfony\Component\Ai\Memory\StaticMemoryProvider();
    $agent->setMemory($memory);
    
  4. Execution:
    $output = $agent->run();
    $output->getContent(); // Final response
    $output->getToolCalls(); // Logged tool invocations
    

Laravel-Specific Patterns

  1. Service Provider Integration:

    // app/Providers/AiServiceProvider.php
    public function register()
    {
        $this->app->singleton(Agent::class, function ($app) {
            return new Agent(
                new Input(''),
                new \Symfony\Component\Ai\Platform\OpenAiPlatform(config('services.openai.key')),
                new \Symfony\Component\Ai\Toolbox\Toolbox([
                    new \Symfony\Component\Ai\Tool\SerpApiTool(config('services.serpapi.key')),
                ])
            );
        });
    }
    
  2. Tool Bridge Registration:

    // app/Providers/AiServiceProvider.php
    public function boot()
    {
        $this->app->bind(
            \Symfony\Component\Ai\Tool\ClockTool::class,
            fn() => new \Symfony\Component\Ai\Tool\ClockTool()
        );
    }
    
  3. Event-Driven Tool Calls (Laravel Events):

    // Listen to tool call events
    event(new \Symfony\Component\Ai\Event\ToolCallRequested(
        $toolCall,
        $agent
    ));
    
  4. Async Processing with Queues:

    // Dispatch agent job
    dispatch(new RunAgentJob($input, $agent));
    

Multi-Agent Orchestration

use Symfony\Component\Ai\MultiAgent\MultiAgent;

$researchAgent = new Agent(/* ... */);
$responseAgent = new Agent(/* ... */);

$multiAgent = new MultiAgent([$researchAgent, $responseAgent]);
$output = $multiAgent->run(new Input('Research and summarize Symfony AI'));

Memory Patterns

  1. Static Memory (In-Memory):
    $memory = new \Symfony\Component\Ai\Memory\StaticMemoryProvider();
    $agent->setMemory($memory);
    
  2. Embedding Memory (Vector Store):
    $store = new \Symfony\Component\Ai\Store\PostgresStore(
        new \Doctrine\DBAL\Connection($connectionParams)
    );
    $memory = new \Symfony\Component\Ai\Memory\EmbeddingProvider($store);
    $agent->setMemory($memory);
    

Structured Output & Progress (v0.15)

  1. Typed structured output — asObject() now accepts an optional class argument, which is what you want for static analysis (PHPStan/Larastan) and IDE autocompletion:
    /** @var \App\Dto\Plan $plan */
    $plan = $output->asObject(\App\Dto\Plan::class);
    
    // Untyped (no static analysis support) still works:
    $plan = $output->asObject();
    
  2. Progress stage constants — use the new constants instead of hard-coded strings when hooking into the agent lifecycle (e.g. to push status updates to the frontend over SSE/queues):
    use Symfony\Component\Ai\Agent\ProgressStage;
    
    $agent->onProgress(function ($stage, $payload) {
        match ($stage) {
            ProgressStage::THINKING => /* ... */,
            ProgressStage::TOOL_CALL => /* ... */,
            ProgressStage::DONE     => /* ... */,
            default => null,
        };
    });
    
    Constants give you a stable contract instead of magic strings that may change between 0.x releases.

Gotchas and Tips

Common Pitfalls

  1. Tool Call Validation Failures:

    • Issue: Tools may reject invalid arguments silently.
    • Fix: Use symfony/validator for argument validation:
      use Symfony\Component\Validator\Constraints as Assert;
      
      #[Tool]
      public function search(string #[Assert\NotBlank] $query): string { ... }
      
  2. Memory Leaks:

    • Issue: Static memory providers retain all conversations.
    • Fix: Use EmbeddingProvider with TTL or clear memory manually:
      $memory->clear();
      
  3. Tool Dispatch Conflicts:

    • Issue: Multiple tools with the same class name may cause ambiguity.
    • Fix: Use unique tool IDs or qualify tool classes:
      $toolbox->addTool(new \App\Tool\CustomBraveSearchTool(), 'custom_brave');
      
  4. Streaming Quirks:

    • Issue: Streaming responses may truncate if not handled properly.
    • Fix: Use DeltaInterface for chunked responses:
      $output->stream(function (DeltaInterface $delta) {
          echo $delta->getContent();
      });
      
  5. Symfony Dependency Conflicts:

    • Issue: symfony/clock or symfony/http-client may conflict with Laravel.
    • Fix: Override bindings in Laravel’s service provider:
      $this->app->bind(\Symfony\Component\Clock\ClockInterface::class, function () {
          return \Illuminate\Support\Facades\Clock::getFacadeRoot();
      });
      
  6. InMemoryPlatform Removed (v0.15, breaking):

    • Issue: Symfony\Component\Ai\Platform\InMemoryPlatform no longer exists. Any test harness or local fake you built on top of it (including the previous MockPlatform example in this doc) will fatal on upgrade.
    • Fix: Switch to MockPlatformFactory:
      use Symfony\Component\Ai\Platform\MockPlatformFactory;
      
      $agent = new Agent(
          new Input('Test'),
          (new MockPlatformFactory())->create()
      );
      
    • Because the whole suite is version-locked, bump all symfony/ai-* packages together (composer require "symfony/ai-*:^0.15") or you will end up with mismatched platform interfaces.

Debugging Tips

  1. Enable Verbose Logging:

    $agent->setLogger(new \Monolog\Logger('ai_agent', [
        new \Monolog\Handler\StreamHandler('storage/logs/ai.log', Monolog\Logger::DEBUG),
    ]));
    
  2. Inspect Tool Calls:

    $output = $agent->run();
    foreach ($output->getToolCalls() as $call) {
        dump($call->getName(), $call->getArguments());
    }
    
  3. Test with the Mock Platform Factory (updated for v0.15):

    use Symfony\Component\Ai\Platform\MockPlatformFactory;
    
    $factory = new MockPlatformFactory();
    $agent = new Agent(new Input('Test'), $factory->create());
    

    Bind the factory in your TestCase::setUp() (or a dedicated FakeAiServiceProvider) so agents resolved from the container are faked consistently across your Laravel feature tests.

  4. Trace Progress Stages:

    foreach ($output->getProgress() as $event) {
        dump($event->getStage()); // compare against ProgressStage::* constants
    }
    

Extension Points

  1. Custom Input/Output Processors:

    class UppercaseOutputProcessor implements OutputProcessorInterface {
        public function __invoke(Output $output): Output {
            $output->setContent(strtoupper($output->getContent()));
            return $output;
        }
    }
    $agent->addOutputProcessor(new UppercaseOutputProcessor());
    
  2. Dynamic Tool Registration:

    $toolbox->addToolsFromDirectory(__DIR__.'/Tools');
    
  3. Override JSON Schema Generation:

    use Symfony\Component\Ai\Tool\Attribute\Tool;
    
    #[Tool(
        schema: [
            'properties' => [
                'query' => ['type' => 'string', 'description' => 'Custom search query']
            ]
        ]
    )]
    public function customSearch(string $query) { ... }
    

Performance Tips

  1. Cache Tool Responses:

    $toolbox->addTool(new \App\Tool\CachedSerpApiTool(
        new \Symfony\Component\Ai\Tool\SerpApiTool('key'),
        new \Illuminate\Cache\Repository
    ));
    
  2. Batch Tool Calls:

    $agent->setToolbox(new \Symfony\Component\Ai\Toolbox\Toolbox([
        new \App\Tool\BatchWebScraperTool(),
    ]));
    
  3. Async Tool Execution:

    $toolbox->addTool(new \App\Tool\AsyncClockTool(
        new \Symfony\Component\Ai\Tool\ClockTool()
    ));
    

Laravel-Specific Quirks

  1. Blade Integration:

    • Use OutputProcessor to render responses:
      $agent->addOutputProcessor(function (Output $output) {
          return new Output(view('ai.response', ['content' => $output->getContent()])->render());
      });
      
  2. Nova Tool Integration:

    • Expose tools as Nova actions:
      public function tools(Nova $nova)
      {
          Nova::tools([
              new \App\Nova\AiSearchTool(),
          ]);
      }
      
  3. Config Caching: agent/platform closures in a service provider are fine, but anything reading config('services.…') at construction time must be resolved lazily (inside the singleton closure) so php artisan config:cache doesn't bake stale keys into a serialized definition.

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-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc