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¶
- See examples directory for standalone agent examples demonstrating core concepts
- Check the bundle's test suite for MockPlatform testing patterns
- Review the Symfony AI Component documentation for complete reference