Laravel AI v0.11.0 est sorti le 19 août 2026 avec 36 pull requests fusionnées et douze contributeurs débutants. Le changement principal est l'observabilité : un identifiant d'invocation unique suit désormais toute l'exécution d'un agent, y compris les tentatives de bascule, et des événements de cycle de vie rendent compte de chaque étape.
Sept pull requests de @pushpak1300 refondent le reporting. Le chemin synchrone prompt() génère désormais l'identifiant d'invocation en amont, comme le faisait déjà streamPrompt() ; auparavant, le middleware synchrone voyait null, et une bascule sur trois fournisseurs produisait trois identifiants sans lien pour une même exécution. Un nouveau RunContext porte l'identité de l'exécution et dispatche directement les événements. L'identifiant d'invocation d'outil est créé dans executeTool(), ce qui corrige un bug d'imbrication où un agent invoqué comme outil écrasait l'identifiant de l'appel externe. Les outils le lisent via Request::toolInvocationId().
StartingStep, StepCompleted et StepFailed se déclenchent autour de chaque aller-retour fournisseur, en synchrone comme en streaming. StartingStep transporte les messages, les options résolues et tout l'historique ; les événements de fin portent la durée en millisecondes, à l'image de QueryExecuted::$time. ToolFailed signale un handler d'outil qui lève une exception, avec son identifiant, avant que l'exception ne soit relancée, et AgentFailed signale un échec terminal une seule fois par exécution, après épuisement de la chaîne de bascule. Un appel d'outil publie ses identifiants, si bien qu'un agent qu'il invoque les hérite comme parentInvocationId et parentToolInvocationId ; le lien ne franchit toutefois pas les frontières de queue.
Un nouveau wrapper ToolSearch de @behzadsp diffère les grands catalogues d'outils : OpenAI et Anthropic les chargent à la demande via leur recherche hébergée au lieu d'envoyer toutes les définitions à chaque requête. Les outils eux-mêmes ne changent pas. Le wrapper correspond à {"type":"tool_search"} chez OpenAI et aux types tool_search_tool_* chez Anthropic, dont la stratégie de recherche est un argument du constructeur validé contre regex et bm25. Les fournisseurs non compatibles lèvent une exception avant l'envoi ; un seul wrapper par requête est autorisé, et la recherche hébergée OpenAI exige des réponses stockées, donc une utilisation avec store=false lève une exception. La même PR ajoute la relecture de sortie sans état pour OpenAI.
La bascule couvre désormais trois cas auparavant manqués. Les ConnectionException, par exemple un hôte injoignable ou une instance Ollama locale arrêtée, sont relancées en ProviderConnectionException implémentant FailoverableException (@JVillator0). La liste des statuts de surcharge passe de 503 seul à 502, 503, 504, 520, 522 et 524 ; le 500 est volontairement exclu (@sulimanbenhalim). Anthropic bénéficie du même traitement. Les refus HTTP 400 d'Anthropic pour plafond de dépenses déclenchent aussi désormais la bascule, après que @oddvalue a signalé environ 990 exceptions non gérées en un mois pour ce cas précis.
Côté fournisseurs : recherche web et recherche de fichiers pour xAI (@timmcleod), transcription pour les fournisseurs compatibles OpenAI et pour Groq, l'outil serveur web fetch pour OpenRouter (@CamilleScholtz), et les citations web fetch d'Anthropic apparaissent sur $response->meta->citations pour les réponses non streamées. Le modèle texte par défaut de Gemini passe à gemini-3.7-flash.
Pour les tests, assertPromptedTimes() rejoint les assertions du fake Promptable, sur le modèle de Bus::assertDispatchedTimes() (@F1nnG), et la génération simulée en file d'attente de transcriptions, images, audio et embeddings exécute désormais le callback then(...) (@gdebrauwer).
Parmi les correctifs mineurs : usage streamé additionné sur les étapes d'appels d'outils, tokens d'écriture de cache OpenAI conservés, tokens de cache hit DeepSeek exclus, filtrage des appels d'outils partiellement orphelins lors du rejeu de l'historique, réparation des appels d'outils locaux inconnus, gestion du contenu en blocs de Mistral, mapping des raisons d'arrêt Anthropic refusal et model_context_window_exceeded, suppression des fences Markdown dans le structured output compatible OpenAI, reconstruction des pièces jointes S3 dans File::fromArray, sources de documents en text/plain chez Anthropic et liaison stable de la requête MCP.
Notes de mise à jour : une erreur fournisseur dans le corps d'un flux lève désormais une StreamErrorException non basculable au lieu de terminer silencieusement l'étape ; l'événement d'erreur du fournisseur est disponible sur ->error. AgentFailedOver prend un nouvel argument obligatoire string $invocationId, ToolInvoked un float $time, et AgentFailedOver ne se déclenche plus pour le dernier fournisseur d'une chaîne. Les applications utilisant le modèle Gemini par défaut passeront à gemini-3.7-flash sauf si le modèle est fixé explicitement. Mise à jour via composer update laravel/ai.
Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.