What Changed in Laravel AI SDK 0.11
Released on August 19, 2026, Laravel AI v0.11.0 ships 36 merged pull requests from twelve first-time contributors. The headline feature is end-to-end observability for agent runs: every run now carries a single correlation ID, and a set of lifecycle events fires around every provider round-trip and every tool call.
Per-Run Invocation IDs
Before this release, prompt() never minted a run-level invocation ID, so synchronous middleware always saw $prompt->invocationId === null. Streaming middleware saw a real value, and a three-provider failover produced three unrelated IDs for the same logical run. prompt() now mints the ID up front, and every provider reuses whatever the caller supplied.
Nested tool calls had a related bug: an agent invoked as a tool overwrote the shared mutable ID before the outer ToolInvoked event fired, so the outer event carried the inner call's ID. The ID is now minted inside executeTool(), and tools can read it with Request::toolInvocationId().
Lifecycle Events
Five events now fire across both the synchronous and streaming paths:
StartingStep— carries the messages, resolved options, and the run's full message history sent to the provider.StepCompleted— carries the complete step response.StepFailed— fires when a step fails; both end events include wall time in milliseconds, matchingQueryExecuted::$time.ToolFailed— reports which tool threw and carries the same tool invocation ID as theInvokingToolthat opened it; the exception is still rethrown.AgentFailed— fires exactly once per run, after failover has exhausted the provider chain.
A tool call also publishes its run and tool invocation IDs for its own duration, so any agent prompted while it runs picks them up as parentInvocationId and parentToolInvocationId. This links sub-agents back to the run that delegated to them without requiring AgentTool.
Hosted Tool Search
Every tool was previously sent to the provider on every request. The new ToolSearch wrapper defers tools so OpenAI and Anthropic load them on demand through their own hosted search:
public function tools(): iterable
{
return [
new WeatherTool,
new ToolSearch(tools: [new SearchInvoices, new RefundOrder]),
];
}
Anthropic's search strategy is a constructor argument validated against regex and bm25:
new ToolSearch(tools: [new SearchInvoices], strategy: 'bm25')
Providers that do not support hosted search throw a clear exception before the request is sent. Only one wrapper may be registered per request, and OpenAI hosted search requires stored responses, so pairing ToolSearch with store=false throws.
Broader Failover Coverage
Three production failure modes now trigger failover where they previously did not:
- Connection failures —
ConnectionException(unreachable host, refused connection, local Ollama not running) is rethrown asProviderConnectionExceptionimplementingFailoverableException. - Gateway error codes — the overloaded-provider status list grew from
503alone to502,503,504,520,522, and524. A bare500is deliberately excluded. - Anthropic spend caps — Anthropic returns HTTP 400 with a
usage limitmessage when an organisation hits its spend cap. Adding that pattern to the failover handler prevents ~990 unhandled exceptions per month in affected setups.
Provider Additions
- xAI: web search and file search
- Groq and OpenAI-compatible providers: transcription
- OpenRouter: web fetch server tool
- Anthropic: web fetch citations now appear on
$response->meta->citations - Gemini: default text model moved to
gemini-3.7-flash
Testing
assertPromptedTimes() works like Bus::assertDispatchedTimes():
SalesCoach::assertPromptedTimes(3);
Faked queued generation of transcriptions, images, audio, and embeddings now runs the then(...) callback, so tests can assert on callback behaviour instead of stopping at the dispatch.
Upgrade Notes
- Stream errors now throw
StreamErrorExceptioninstead of silently ending the step. AgentFailedOverrequires a newstring $invocationIdargument;ToolInvokedrequires a newfloat $timeargument. Only code constructing these events by hand needs updating.AgentFailedOverno longer fires for the final provider in a chain;AgentFailedhandles that case.- Applications relying on Gemini's default text model will move to
gemini-3.7-flash; set the model explicitly to keep the old one.
Key takeaways:
- Every agent run now has a single correlation ID across failover attempts.
- Five lifecycle events with wall timings make multi-step runs fully traceable.
ToolSearchreduces token usage by deferring tool loading to the provider.- Failover now handles connection errors, gateway timeouts, and Anthropic spend caps.
assertPromptedTimes()simplifies agent test assertions.
Upgrade with composer update laravel/ai. Full details at the Laravel News source article.