Upgrading
Changes within 3.x that can affect existing code. The full list is in CHANGELOG.
After every upgrade publish new migrations and check the schema:
php artisan vendor:publish --tag=ai-migrationsphp artisan migratephp artisan about # AI Tasks section- A run that stops before a tool needing approval gets status
pausedinstead ofok. Queries and reports filteringstatus = 'ok'miss these runs;postprocess()/onCompleted()still run for them. - A paused run is no longer retried when
isAcceptable()rejects it. - A pause continued by hand (
AiPayload::$decisions) is invisible to the package and stayspaused; continue withAI::resume()to have it closed, claimed once and expired. AiResponsehas new trailing constructor argumentsresumeMessagesandrunId.- New config section
approvals(php artisan aboutlists it as missing in a published config).
- Tasks can carry request state into the worker:
ActsAsDispatchingUser, orexecutionContext()/withExecutionContext(). Nothing changes for tasks that don’t use them. AiRun::start()/startAsQueue()take a new trailing$executionContextargument; direct callers are unaffected.- Dashboard Retry and
ai:retryrebuild the task under the run’s stored context. Runs dispatched before 3.34 have none and are retried as before.
- New
ai_runs.user_idcolumn — publish and run the migration. Until then runs are stored without it and the dashboard’s User filter has no effect. AiContexthas a new trailing constructor argumentuserId. Code that builds anAiContextitself is unaffected.
AI::queue()uses the whole routing chain and falls back to the next driver within one attempt.ai_runs.driverof a queued run is the driver that answered, not always the first one.- No fallback when the provider rejects the request (4xx other than 408/429) —
send()/stream()throwAiDriverExceptionright away. Before, any error moved on to the next driver. stream()doesn’t switch drivers once output has started.AiRunFailedfires once per queued run, after the queue gives up — not on every attempt. Between attempts the run staysrunning.
3.28 — laravel/ai 1.0
Section titled “3.28 — laravel/ai 1.0”- Requires
laravel/ai^1.0; if the app useslaravel/mcpdirectly, it must be^1.0. - Bedrock:
composer require aws/aws-sdk-php, laravel/ai no longer installs it. - Gemini raw
provider_optionsuse the Interactions API names (thinkingConfig→thinking_level), see the laravel/ai upgrade guide. tokens_outincludes reasoning tokens for every provider — runs with Anthropic extended thinking show highertokens_outandcost.- A missing
cache_read/cache_writerate falls back toininstead of costing cached tokens as free. Set the rate to0to keep the old behaviour.
- New
ai_runs.cost_ratescolumn — publish and run the migration. Until then runs are stored without it.
- The dashboard has Retry / Dead actions under
dashboard.middleware, which defaults to['web']— no authorization. Add your auth middleware. ai:request --temperatureis sent only when given.
- A run rejected by the post-call budget check is recorded as
error(with its cost), notok. Code that sums spend bystatus = 'ok'should usecost IS NOT NULL.
temperature,max_tokens,top_pin payload options now reach the provider — outputs of tasks that already declared them change.viaQueues()['post']is honoured — make sure workers consume that queue.ai:retryre-dispatches runs;--dry-runkeeps the old list-only behaviour.- Global postprocess pipes also run on the queued path and on
stream(). AI::fake()callsonCompleted()and firesAiTaskCompletedforsend()/stream().stream()times out after 60 seconds by default, likesend().- The OpenAI webhook handler verifies Standard Webhooks signatures — set
OPENAI_WEBHOOK_SECRETto thewhsec_...value. Thewebhook.signature_headerconfig key was removed.
2.x → 3.0
Section titled “2.x → 3.0”- Engine replaced:
prism-php/prism→laravel/ai. PHP ^8.3, Laravel ^12. - Config renamed:
config/ai.php→config/ai-tasks.php.config/ai.phpnow belongs to laravel/ai and holds the credentials.