APPs inteligentes con agentes de IA en PHP Symfony

Durante años, integrar modelos de lenguaje en aplicaciones PHP implicaba construir adaptadores manuales, gestionar llamadas HTTP complejas y diseñar sistemas improvisados para manejar el contexto.

Con la llegada de Symfony AI Agent Component, el ecosistema PHP da un paso importante hacia un enfoque más estructurado. Symfony introduce una forma nativa, tipada y alineada con su filosofía de arquitectura para integrar LLMs dentro de aplicaciones empresariales.

No se trata simplemente de “conectar con un modelo de IA”. El verdadero cambio está en cómo se integra la inteligencia dentro del dominio de la aplicación.

Es por ello que en este artículo exploramos cómo diseñar aplicaciones ‘inteligentes’ con Symfony siguiendo buenas prácticas de arquitectura, mantenibilidad y testabilidad.

La IA como parte de la arquitectura, no como un script

Uno de los errores más comunes al integrar IA en aplicaciones es tratarla como un servicio externo aislado.

Muchos proyectos empiezan con algo parecido a esto:

$response = $httpClient->request('POST', 'https://api.openai.com/v1/chat/completions', [...]);

Funciona… pero rompe varios principios fundamentales, ya que no hay tipado, no hay control estructurado del contexto, no hay integración con el contenedor de servicios y es difícil de testear.

Symfony resuelve esto introduciendo el concepto de Agent, un servicio que encapsula el modelo utilizado, el contexto, las herramientas disponibles y el comportamiento esperado. 

Es decir, la inteligencia se convierte en parte del dominio de la aplicación.

Configuración centralizada de los agentes

Siguiendo la filosofía de Symfony, los agentes no se crean manualmente en el código.

Se definen en la configuración del sistema.

ai:
  platform:
    openai:
      api_key: '%env(OPENAI_API_KEY)%'
  agent:
    default:
      model: 'gpt-4o-mini'
      prompt: 'You are a helpful Symfony assistant. concise and technical.'
    support_bot:
      model: 'gpt-4o'
      prompt: 'You are a customer support agent. Be polite and empathetic.'

Este enfoque aporta varias ventajas, ya que podrás centralizar los modelos y los prompts, reutilizar agentes, cambiar en cualquier momento de proveedor de IA y te permitira una mejor integración con el contenedor de dependencias.

Desde el punto de vista arquitectónico, los agentes se convierten en servicios de infraestructura.

Inyección de dependencias: la forma Symfony

Una vez definido el agente, se puede inyectar directamente en cualquier servicio de la aplicación.

{
    public function __construct(
        #[Autowire(service: 'ai.agent.support_bot')]
        private AgentInterface $agent
    ) {}

    public function ask(string $question): string
    {
        $messages = new MessageBag(
            Message::ofUser($question)
        );

        $response = $this->agent->call($messages);

        return $response->getContent();
    }
}

Aquí se observa algo importante, la interacción con el modelo se convierte en una llamada de dominio, no en una petición HTTP, olvídate de cambios en la API.

Esto permite mantener una arquitectura limpia desacoplada de la lógica del proveedor de IA y facilit el testing.

Tools: cuando la IA puede ejecutar acciones

El verdadero potencial de los agentes aparece cuando pueden utilizar Tools.

Una Tool es simplemente una función que el modelo puede invocar para por ejemplo consultar datos, ejecutar acciones o interactuar con el sistema.

Symfony permite definir estas herramientas mediante atributos.

    name: 'get_order_status',
    description: 'Retrieves the current status of a customer order.'
)]
final readonly class OrderStatusTool
{
    public function __invoke(
        string $orderId,
        OrderRegion $region
    ): string {
        return sprintf(
            "Order %s in region %s is currently: SHIPPED",
            $orderId,
            $region->value
        );
    }
}

Lo interesante es que Symfony genera automáticamente el JSON Schema necesario para el modelo, por lo que esto evita errores frecuentes en integraciones manuales.

La importancia del tipado: evitar alucinaciones

Una práctica especialmente interesante es el uso de Enums.

{
    case US = 'us';
    case EU = 'eu';
    case ASIA = 'asia';
}

Gracias a esto, el sistema genera un esquema JSON que limita los valores posibles, en lugar de aceptar cualquier texto del modelo, el sistema fuerza a que la IA solo pueda elegir entre: us, eu o asia.

Esto reduce significativamente uno de los problemas clásicos de los LLM, las alucinaciones en parámetros estructurados.

Procesadores de entrada: añadir contexto dinámico

Muchas aplicaciones necesitan proporcionar información adicional al modelo antes de cada llamada.

Por ejemplo el usuario actual, permisos, historial de acciones o estado de la aplicación.

Symfony permite interceptar la entrada mediante Input Processors.

{
    public function __construct(private Security $security) {}

    public function processInput(Input $input): void
    {
        $user = $this->security->getUser();

        if ($user) {
            $input->setMessageBag(
                (new MessageBag(
                    new SystemMessage(
                        sprintf("Current user is %s (ID: %d)", $user->getEmail(), $user->getId())
                    )
                ))->merge($input->getMessageBag())
            );
        }
    }
}

Este patrón permite construir lo que podríamos llamar RAG ligero, sin necesidad de implementar sistemas complejos de recuperación documental.

Testing de agentes sin consumir APIs

Uno de los mayores problemas al trabajar con IA es el testing ya que las respuestas no siempre son deterministas, consumen créditos de API y pueden cambiar entre versiones de modelo.

Para esto Symfony introduce MockAgent, que permite simular respuestas.

    'how do I reset my password?' => 'Go to settings and click reset.',
]);

Esto permite escribir tests rápidos y predecibles, así la lógica de negocio se valida sin depender del modelo real.

La llegada de una nueva capa en las aplicaciones

Durante años las aplicaciones web se han estructurado en tres grandes capas datos, lógica y presentación, con la llegada de la IA, la integración introduce una cuarta capa emergente, la capa cognitiva.

Frameworks como Symfony están empezando a formalizar esta capa mediante conceptos como Agents, Tools, Context processors y Structured outputs, que permiten diseñar aplicaciones donde la inteligencia artificial no es un añadido, sino un componente estructural del sistema.

Conclusión

La introducción del Symfony AI Agent Component representa un paso importante para el ecosistema PHP. Permite integrar modelos de lenguaje dentro de aplicaciones empresariales manteniendo arquitectura limpia, tipado fuerte, integración con el contenedor de servicios y testing fiable.

Más allá de la tecnología concreta, el cambio interesante es conceptual, no se trata de “usar IA”, se trata de diseñar software donde la inteligencia es una capacidad del sistema, igual que lo son hoy las bases de datos o los sistemas de mensajería.

Symfony está empezando a ofrecer las herramientas para hacerlo de forma robusta y eso abre una nueva etapa en el desarrollo de aplicaciones inteligentes.