Skip to content

Symfony Agent Integration

Overview

This guide shows how to configure and use AI agents in your Symfony application. Unlike the standalone examples which manually create the platform, Symfony applications configure agents through YAML and inject them as services.

Agent Configuration

Agents are configured through the ai.agent configuration in config/packages/ai.yaml, not as manual service definitions.

Example configuration:

ai:
    agent:
        # Default agent using sulu.ai platform
        default:
            platform: 'sulu_ai_platform.platform'
            model: 'default'

        # Weather agent with tools
        weather_agent:
            platform: 'sulu_ai_platform.platform'
            model: 'gpt-4o'
            prompt:
                text: 'You are a helpful weather assistant.'
                include_tools: true
            tools:
                - 'App\AI\Tool\WeatherService'

Using Agents in Services

Services inject the AgentInterface to use configured agents:

<?php

namespace App\Service;

use Symfony\AI\Agent\AgentInterface;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

final readonly class WeatherService
{
    public function __construct(
        private AgentInterface $agent,
    ) {
    }

    public function getWeather(string $city): string
    {
        $messages = new MessageBag(Message::ofUser("What's the weather in {$city}?"));
        $response = $this->agent->call($messages);

        return $response->getContent();
    }
}

Injecting Specific Named Agents

To use a specific agent instead of the default:

<?php

namespace App\Service;

use Symfony\AI\Agent\AgentInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

final readonly class WeatherService
{
    public function __construct(
        #[Autowire(service: 'ai.agent.weather_agent')]
        private AgentInterface $weatherAgent,
    ) {
    }

    public function getWeather(string $city): string
    {
        $messages = new MessageBag(Message::ofUser("What's the weather in {$city}?"));
        $response = $this->weatherAgent->call($messages);

        return $response->getContent();
    }
}

Using Agents in Controllers

Inject the configured agent into controllers:

<?php

namespace App\Controller;

use Symfony\AI\Agent\AgentInterface;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class WeatherController extends AbstractController
{
    public function __construct(
        #[Autowire(service: 'ai.agent.weather_agent')]
        private readonly AgentInterface $weatherAgent
    ) {
    }

    public function getWeather(Request $request): Response
    {
        $city = $request->get('city', 'Berlin');
        $messages = new MessageBag(Message::ofUser("What's the weather in {$city}?"));
        $result = $this->weatherAgent->call($messages);

        return new JsonResponse(['weather' => $result->getContent()]);
    }
}

Registering Tools with Agents

Tools are registered and configured through the agent configuration:

# config/packages/ai.yaml
ai:
    agent:
        weather_agent:
            platform: 'sulu_ai_platform.platform'
            model: 'gpt-4o'
            prompt:
                text: 'You are a helpful weather assistant.'
                include_tools: true
            tools:
                - 'App\AI\Tool\WeatherService'

Tools must be registered as services with the #[AsTool] attribute or tagged with ai.tool:

<?php

namespace App\AI\Tool;

use Symfony\AI\Agent\Toolbox\Attribute\AsTool;

#[AsTool]
class WeatherService
{
    public function getCurrentWeather(string $city): array
    {
        // In a real implementation, this would call a weather API
        return [
            'temperature' => 22,
            'conditions' => 'sunny',
            'city' => $city,
            'humidity' => 65,
            'wind_speed' => 12,
        ];
    }
}

Using Intelligent Search as a Tool

Agents can use Intelligent Search as a tool — the agent decides when to look something up in your Sulu content and grounds its answers in the search results, citations included.

Wrap the search client in a tool class:

<?php

namespace App\AI\Tool;

use Sulu\Bundle\AiPlatformBundle\IntelligentSearch\Client\IntelligentSearchClientInterface;
use Sulu\Bundle\AiPlatformBundle\IntelligentSearch\Query\IntelligentSearchQuery;
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;

#[AsTool(
    name: 'content_search',
    description: 'Searches the website content and returns an answer with source citations. Use this to answer questions about the website, products, or documentation.',
)]
final readonly class ContentSearchTool
{
    public function __construct(
        private IntelligentSearchClientInterface $intelligentSearch,
    ) {
    }

    /**
     * @param string $question The natural-language question to search for
     * @param string $locale   The locale to search in (e.g. "en")
     */
    public function __invoke(string $question, string $locale = 'en'): string
    {
        $query = IntelligentSearchQuery::create($question, $locale);
        $result = $this->intelligentSearch->search($query);

        $sources = '';
        foreach ($result->sources as $source) {
            $sources .= \sprintf("\n[%d] %s (%s)", $source->citationNumber, $source->title, $source->url);
        }

        return $result->answer . "\n\nSources:" . $sources;
    }
}

Then register the tool on your agent:

# config/packages/ai.yaml
ai:
    agent:
        support_agent:
            platform: 'sulu_ai_platform.platform'
            model: 'default'
            prompt:
                text: 'You are a support assistant. Answer questions using the content_search tool and always mention your sources.'
                include_tools: true
            tools:
                - 'App\AI\Tool\ContentSearchTool'

Notes:

  • Intelligent search must be enabled and ingested — the tool searches the same index as the public endpoint and CLI.
  • The query supports the same refinements as everywhere else (withBuckets(), withWebspaceKey(), withPreferRecent(), withSince()) — see Searching → Query Builder. Fix buckets or the webspace in the tool when the agent should only see a slice of the content.
  • Returning the citations as part of the tool result lets the agent quote its sources in the final answer.

Further Reading

Sources