📡 Laravel PAO : la sortie optimisée pour les agents IA
📚 Introduction
Faire collaborer un agent IA avec une stack PHP suppose qu’il puisse lire la sortie des outils : tests qui échouent, alertes PHPStan, suggestions Rector, retour d’une commande Artisan. Le problème, c’est que ces sorties sont historiquement conçues pour des humains : couleurs ANSI, alignement à la colonne, séparateurs visuels, formats hétérogènes.
Laravel PAO (Agent-Optimized Output) règle ce problème. C’est un wrapper qui réécrit en temps réel la sortie des outils PHP courants dans un format structuré, déterministe et économe en tokens. Et malgré le nom, il fonctionne avec n’importe quel projet PHP : Laravel bien sûr, mais aussi Symfony, Laminas, ou un projet vanilla qui utilise PHPUnit.
🧩 Les outils couverts
PAO sait reformater la sortie de :
- PHPUnit 12 et 13.
- Pest 4 et 5 (tests unitaires et fonctionnels).
- Paratest (exécution parallèle des suites de tests).
- PHPStan (analyse statique).
- Rector (modernisation automatique de code).
- Artisan (commandes Laravel 12+), avec un module dédié qui nettoie les ANSI et réduit la verbosité des outputs courants.
À chaque fois, l’idée est la même : retirer le bruit visuel, compacter le format en JSON déterministe, et présenter l’essentiel à l’agent.
🚀 Mise en place
Installation classique :
composer require laravel/pao --devEt… c’est tout. Il n’y a pas de binaire pao à appeler ni de wrapper à préfixer. PAO s’enregistre via l’autoloader Composer, auto-discover un service provider côté Laravel, et hook les sorties de PHPUnit, Pest, Paratest, PHPStan et Rector à l’exécution :
# Vos commandes restent strictement identiques
./vendor/bin/pest
./vendor/bin/phpstan analyse
./vendor/bin/rector process --dry-run
php artisan migrate --pretendLa vraie astuce, c’est la détection d’environnement : PAO ne se déclenche que lorsqu’il détecte une session d’agent (Claude Code, Cursor, Devin, Gemini CLI, etc., via des variables d’environnement bien connues). En terminal humain, la sortie reste strictement inchangée — couleurs ANSI, tableaux, badges, tout est préservé. Pas de “mode dégradé” à subir pour le développeur.
Côté agent, la même commande renvoie un JSON compact. Sur une suite de 1 000 tests qui passe, on peut tomber à un seul objet { "tests": 1000, "duration": "...", "failures": [] }. L’équipe Laravel annonce jusqu’à 99,8 % de tokens en moins sur ce type de cas — chiffre à prendre comme un plafond, mais la tendance est nette dès qu’on en fait l’expérience.
🤖 L’effet concret côté agent
Sur une session Claude Code, voici ce que PAO change concrètement.
Avant PAO, demander “lance les tests et corrige ce qui échoue” produit une longue sortie ANSI, dont l’agent doit extraire à la main les tests en erreur, les fichiers concernés et les messages d’assertion. Les tokens dépensés sont importants, et la précision parfois discutable.
Avec PAO, la sortie est déjà structurée : un objet par test échoué, avec son nom, son fichier, sa ligne, son message et son diff. L’agent attaque directement la correction, sans la phase de parsing. Sur une grosse suite, on observe une réduction nette de la consommation de tokens et un taux de succès plus élevé sur les corrections proposées.
🧠 Combiner PAO avec Boost
C’est la combinaison qui rend l’écosystème vraiment cohérent. Laravel Boost expose l’application Laravel comme un serveur MCP exploitable par l’agent : routes, modèles, schéma de base, exécution Tinker. PAO complète le tableau en exposant la sortie des outils du même projet dans un format que l’agent comprend nativement.
Sur un workflow typique :
- L’agent demande à Boost l’état du schéma et des modèles.
- Il propose une migration ou une refonte.
- Il lance
./vendor/bin/pestpour vérifier que les tests passent (PAO se charge silencieusement de compacter la sortie). - Il lance
./vendor/bin/phpstan analysepour s’assurer qu’il n’a pas introduit de régression statique. - Sur échec, il interprète directement le JSON normalisé et corrige.
La boucle “code → test → corrige” se ferme dans une seule conversation, sans qu’on ait à recopier les sorties à la main.
🛠️ Au-delà de l’agent : un format utile aussi pour la CI
Dans un pipeline CI, la détection d’agent ne s’active pas — la sortie reste donc humaine, ce qui est ce qu’on veut pour lire le log d’un job qui casse. Si vous voulez forcer le format JSON compact en CI pour le parser ensuite (annotations PR, checks GitHub, dashboards), c’est faisable en exportant la variable d’environnement attendue par PAO avant d’exécuter la commande. Quelques pistes typiques :
- Publier le résultat de PHPStan sous forme de checks GitHub précis (fichier et ligne par finding).
- Croiser le résultat de Pest avec les commentaires de PR pour annoter directement les tests cassés.
- Stocker l’historique d’évolution du coverage ou des findings PHPStan dans un dashboard, sans dépendre d’un fichier de log fragile.
C’est typiquement le type d’évolution qu’on peut intégrer à une pipeline GitHub Actions existante en quelques heures.
⚠️ Quelques précautions
- Installer en
require-dev: comme Pail ou Pint, PAO n’a rien à faire en production. - Vérifier les versions des outils sous-jacents : PAO supporte PHPUnit 12-13, Pest 4-5, et Laravel 12+ côté Artisan. Sur un projet plus ancien, mettre à jour ces dépendances avant d’ajouter PAO.
- Penser hors-Laravel : malgré le namespace, PAO marche sur Symfony, Laminas ou un projet vanilla. Aucun service provider Laravel n’est exigé pour PHPUnit / Pest / PHPStan / Rector ; seul le module Artisan demande un projet Laravel.
🎉 Conclusion
Laravel PAO est l’une de ces briques qu’on n’attendait pas mais qui change l’ergonomie une fois adoptée. Pour les équipes qui travaillent avec Claude Code, Cursor ou un agent custom sur un projet PHP, c’est probablement le complément naturel de Laravel Boost : Boost expose l’application, PAO expose les outils, et l’agent peut désormais boucler sur un cycle complet de développement sans intermédiaire.
L’adoption est triviale (un seul composer require --dev, aucune commande à préfixer), réversible immédiatement, et compatible avec n’importe quel projet PHP, pas seulement Laravel. Bref, c’est le genre de package qui mérite d’être ajouté au composer.json cette semaine.
🔗 Liens utiles
/faq
Questions fréquentes
Qu'est-ce que Laravel PAO ?
+
Laravel PAO (Agent-Optimized Output) est un wrapper qui réécrit en temps réel la sortie des outils PHP courants (PHPUnit, Pest, Paratest, PHPStan, Rector, Artisan) dans un format structuré, déterministe et économe en tokens, exploitable par un agent IA.
Laravel PAO fonctionne-t-il uniquement avec Laravel ?
+
Non, malgré son nom PAO fonctionne avec n'importe quel projet PHP (Symfony, Laminas ou un projet vanilla). Seul le module Artisan demande un projet Laravel ; PHPUnit, Pest, PHPStan et Rector n'exigent aucun service provider Laravel.
Comment PAO évite-t-il de dégrader la sortie pour un développeur humain ?
+
PAO détecte l'environnement et ne se déclenche que lorsqu'il repère une session d'agent (Claude Code, Cursor, Devin, Gemini CLI) via des variables d'environnement. En terminal humain, la sortie reste strictement inchangée avec couleurs, tableaux et badges.