• 6 min read

Laravel AI SDK 1.1: Agent Skills, Tool Approval, and Safer Failover

Laravel AI SDK 1.1 adds Agent Skills, approval for built-in tools and safer provider failover. Here is what changed and what to check before upgrading.

Featured image for "Laravel AI SDK 1.1: Agent Skills, Tool Approval, and Safer Failover"

The Laravel AI SDK shipped its first minor release since 1.0 on October 7, 2026. Version 1.1.0 is not a flashy release, but three of its changes affect how you build agents that run in production: support for the Agent Skills format, approval gates on the built-in tools, and a failover fix that stops a run from dying when the backup provider lacks a tool. This post walks through each one with code, and flags what to check before you upgrade.

Everything here comes from the Laravel News write-up of the release and the v1.1.0 release notes. I have not run these examples against a live provider, so treat the snippets as adapted from those sources and test them in your own app.

Upgrading

composer require laravel/ai:^1.1

Approval is off by default, so existing agents behave the same after the upgrade. One change can surprise you, though. The release updates the fallback models for most providers. According to Laravel News, Anthropic now defaults to claude-sonnet-5-5 and Gemini to gemini-3.8-flash. If you rely on those defaults instead of setting models in config/ai.php, your app will use the newer models as soon as you upgrade. Pin your models explicitly if you care about cost or output stability.

Agent Skills

Agent Skills is a folder format that coding agents use to load instructions only when a task needs them. A skill is a directory with a SKILL.md file. The frontmatter needs a description, and the name is optional and defaults to the folder name.

Laravel News notes that the team turned down skills support twice before, and changed course once the format became a standard many tools use. That matters for a practical reason: if your coding agent already reads skills from .agents/skills, your application’s agents can read the same files.

A skill folder looks like this:

resources/skills/
└── refund-policy/
    ├── SKILL.md
    └── references/EDGE-CASES.md

And the SKILL.md itself:

---
name: refund-policy
description: Use when a customer asks for a refund or a partial credit.
---

Check the order date first. Orders older than 30 days...

To hand skills to an agent, implement the new HasSkills contract and return your sources from skills():

<?php

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasSkills;
use Laravel\Ai\Promptable;
use Laravel\Ai\Skills\Skill;

class SupportAgent implements Agent, HasSkills
{
    use Promptable;

    public function instructions(): string
    {
        return 'You are a support agent.';
    }

    public function skills(): iterable
    {
        return [
            resource_path('skills'),
            base_path('.agents/skills'),
            new Skill(
                name: 'house-style',
                description: 'Use when you write copy for a customer.',
                instructions: view('skills.house-style', ['brand' => $this->brand]),
            ),
            fn () => $this->user->team->skills->map->toSkill(),
        ];
    }
}

A source can be a directory, a Skill object built in PHP, or a closure. The SDK runs the closure the first time the tool reads its skills, which means you can load skills from the database per user or per team. That is the interesting part for multi-tenant apps, where each customer might want their own tone or policy rules.

How it works under the hood

The agent gets a single LoadSkill tool. That tool lists each skill’s name and description. The model calls it to read a skill’s full instructions, and calls it again with a path to read a file bundled with the skill, such as references/EDGE-CASES.md.

This is the point of skills: the model sees a short list of descriptions up front, and pays for the long instructions only when a task calls for them.

Two details from the release notes: the tool only reads bundled files from inside the skill’s folder, and it rejects files larger than 256 KB and binary files. Because the description is what the model uses to decide when to load a skill, write it as a trigger condition (“Use when a customer asks for a refund”), not as a title.

Approval for built-in tools

The MCP, agent, similarity search, and filesystem tools now implement the Approvable contract. You can call requireApproval() on them directly. Before this release, you had to subclass a tool to gate it.

The release notes give a useful example. This requires approval for every GitHub MCP tool that is not marked read-only:

use Laravel\Ai\Tools\McpTool;

$github->tools()
    ->mapInto(McpTool::class)
    ->map(fn (McpTool $tool) => ($tool->annotations()['readOnlyHint'] ?? false)
        ? $tool
        : $tool->requireApproval());

The pattern is the one to copy. Let read-only tools run freely, and put a human in front of anything that writes, deletes, or sends. MCP servers can mark tools with a readOnlyHint annotation, and this code trusts that annotation. If you connect a server you do not control, remember that the hint is the server’s claim, not something the SDK verifies. For third-party servers, you may prefer to gate everything and loosen later.

Laravel News points to its earlier post on human-in-the-loop tool approval for how the approval flow itself works, so start there if you have not used it.

Failover that does not fall over

Failover lets you list several providers and have the SDK move to the next one when a request fails, for example on a rate limit. Before 1.1, there was a trap. Say an agent uses the WebFetch and WebSearch provider tools on ['anthropic', 'openai']. A rate-limited Anthropic request would move to OpenAI, and OpenAI would throw:

RuntimeException: Provider [openai] does not support the [WebFetch] tool.

Now the text generation loop removes the provider tools that the current provider does not support before each attempt. The run continues with WebSearch only. On a provider without hosted tool search, the SDK unwraps ToolSearch and sends its tools as regular tools. More than one ToolSearch wrapper still throws on every provider.

The trade-off is worth stating plainly. The run now succeeds, but with fewer capabilities than the first provider had. If your prompt depends on fetching a page, a silent fallback to search-only could produce a weaker answer without any error to alert you. Log which provider handled the request, and consider whether some agents should fail loudly instead.

Smaller additions

A few other changes in the release:

  • Cohere text generation. Cohere was already supported for embeddings and reranking. 1.1 adds chat through Cohere’s v2 Chat API, with streaming, tool calls, structured output and reasoning. Use it with (new SupportAgent)->prompt('Hello', provider: 'cohere'). The default model is command-a-03-2025. Cohere cannot force a specific tool, and document attachments and citations are not supported yet.
  • Self-hosted Laya classification. Point the typesafe driver at a self-hosted Laya server by setting a url on the connection.
  • A MoveFile tool. Agents can rename or move a file in one tool call instead of copying and deleting.

A practical upgrade checklist

  1. Run composer require laravel/ai:^1.1 on a branch.
  2. Check config/ai.php. If any provider has no explicit model, decide whether the new default is acceptable and pin the one you want.
  3. Move long, situational instructions out of instructions() and into skills, starting with the one that is longest and used least.
  4. Audit every MCP and filesystem tool your agents use. Add requireApproval() to anything that changes state.
  5. If you use failover, add logging for the provider that actually answered.

Picture a PHP Architect subscriber support agent. Refund rules live in skills the model loads on demand, and any tool that touches a customer’s account waits for a human. The 1.1 release tightens the parts that matter once an agent does real work: where instructions live, who signs off on risky actions, and what happens when a provider fails.

Sources