Laravel AI SDK reaches 1.0.0 after months in beta. The official package unifies OpenAI, Anthropic, Gemini, and others through one API via `composer require laravel/ai`.

terminal
composer require laravel/ai

Classification using TypeSafe's Jev model is the headline. Jev handles fast, cheap yes/no and pick-one decisions: a support ticket gets flagged `is_urgent` and routed to `billing`, `technical`, or `sales`. Single binary questions use `Str::of($message)->decide('Is this spam?');` TypeSafe and OpenRouter work today; more providers follow the same interface.

Streaming now speaks Vercel Chat and AG-UI protocols directly. A route with `Vercel::chat($request)`, `withMessages()`, and `stream()` loads conversation history, saves it, and processes pending tool approvals. AG-UI clients like CopilotKit swap in `usingAgentUserInteractionProtocol()`.

Risky tools pause for human sign-off. A `DeleteFile` class implements `Approvable` and `Tool` with `InteractsWithApprovals`. Approve, reject with a reason the model sees, or edit arguments before execution runs.

Other 1.0 additions: middleware runs every generation step (not just once); `ToolSearch` lazy-loads rarely-used tools on OpenAI and Anthropic; `CodeExecution` runs code in Anthropic, OpenAI, Azure, Gemini, and xAI sandboxes. Conversation history moves to a single `steps` column—apps querying old columns need migration.

Laravel Boost streamlines the upgrade: `composer require laravel/boost --dev`, then `php artisan boost:install`, then run `/upgrade-ai-sdk-v1` in Claude Code or Cursor to guide the migration.

Laravel 13.33 arrives with smaller, practical fixes. `Cache::memo()` now accepts `tags`, so memoized reads within a request stay tagged: `Cache::memo()->tags(['permissions'])->get(...)`. Repeated permission or settings lookups dodge extra Redis trips.

The `#[Refreshes]` attribute handles database-computed columns. Mark `#[Refreshes('net_salary')]` on a model where `net_salary` derives from `base_salary + allowance - deduction` via stored expression. After create or update, Laravel queries that column alone and updates the model object. Multiple columns: `#[Refreshes('net_salary', 'tax_status')]`. Each save pays the cost of one small query (`select net_salary from employees where id = ? limit 1`). Use manual `refresh()` for rare, one-off needs.

`AsCollection::nullable()` and `AsArrayObject::nullable()` now store real SQL NULL instead of the string "null", so `whereNull()` finds them. `inplace()` and `lock()` modifiers request `ALGORITHM=INPLACE` and `LOCK=NONE` on index and foreign-key migrations for large MySQL tables. Form Request attributes like `#[StopOnFirstFailure]` inherit from parent classes. `Worker::$killOnTimeout = false` lets a timed-out job throw and clean up without killing the worker. `mockArtisan()` and `realArtisan()` separate mock from real command runs without toggling `$mockConsoleOutput`.