DEV Community

Cover image for Laravel AI SDK 1.1 Agent Skills: Setup Guide and Gotchas
devTalk
devTalk

Posted on Originally published at dev-talk.com

Laravel AI SDK 1.1 Agent Skills: Setup Guide and Gotchas

If you build an AI agent, its instructions tend to grow. First it is two lines, then it is your refund rules, your shipping rules, your tone of voice, and a pile of examples. Every request sends all of it to the model, whether the question needs it or not. Laravel AI SDK 1.1, released on 5 October 2026, adds agent skills to fix exactly that: you split the instructions into small folders, and the model loads a folder only when the question calls for it.

What a skill is

A skill is a folder with a SKILL.md file in it. The file has a short description at the top and the full instructions below. The agent always sees the list of names and descriptions. It reads the full text only when it decides a skill is relevant. Think of a table of contents that the model can open chapter by chapter.

Set it up in four steps

1. Install or upgrade

composer require laravel/ai:^1.1
Enter fullscreen mode Exit fullscreen mode

The package's composer.json asks for PHP 8.3 or newer and illuminate/support 12 or 13, and it needs symfony/yaml to read the skill files.

2. Create a skill

Put one folder per skill under resources/skills:

resources/skills/
└── refund-policy/
    ├── SKILL.md
    └── templates/
        └── reply.md
Enter fullscreen mode Exit fullscreen mode
---
name: refund-policy
description: "Use when a customer asks for a refund or a partial credit."
---

# Refund policy

Refunds are allowed within 30 days.
See templates/reply.md for the wording.
Enter fullscreen mode Exit fullscreen mode

The description is required. The name is optional and falls back to the folder name. Write the description as a trigger, starting with "Use when...", because it is the only thing the model sees until it loads the skill.

3. Tell your agent to use skills

Implement the HasSkills contract and return where the skills live:

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasSkills;
use Laravel\Ai\Promptable;
use Stringable;

class SupportAgent implements Agent, HasSkills
{
    use Promptable;

    public function instructions(): Stringable|string
    {
        return 'You are a support assistant for Acme.';
    }

    public function skills(): iterable
    {
        return [resource_path('skills')];
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Prompt it as usual

$response = (new SupportAgent)->prompt('Can I get a refund for order 1042?');
Enter fullscreen mode Exit fullscreen mode

That is all. Behind the scenes the SDK gives the agent one extra tool, LoadSkill, so you never add it by hand.

What the model actually sees

I ran the real LoadSkill tool against a set of test skill folders (the extra names below, custom-name and secret, are just my fixtures). The tool's description, which is what the model reads up front, looks like this:

Load a skill's instructions before performing a task matching the skill's description. Pass a path to read one of the skill's bundled files instead.

Available skills:
- custom-name: Folder differs from name.
- refund-policy: Use when a customer asks for a refund or a partial credit.
- secret: Secret skill.
- shipping: Use for shipping and delivery questions.
Enter fullscreen mode Exit fullscreen mode

The skill names are also offered as a fixed list of allowed values for the tool's name argument. When the model loads refund-policy, it gets the body of the file plus a list of the other files in the folder:

<skill_content name="refund-policy">
# Refund policy

Refunds are allowed within 30 days.
See templates/reply.md for the wording.

<skill_resources>
templates/reply.md
</skill_resources>
Read one of these files by calling this tool again with the skill name and the file's path.
</skill_content>
Enter fullscreen mode Exit fullscreen mode

To read templates/reply.md the model calls the tool a second time with a path. So your tokens are spent in three layers: names and descriptions always, instructions when needed, extra files only if the instructions send the model there.

Other ways to supply skills

skills() can return a mix of directories, Skill objects built in PHP, and closures. A closure runs the first time the tool needs the skills, so you can load them from a database, for example per user or per tenant:

use Laravel\Ai\Skills\Skill;

public function skills(): iterable
{
    return [
        resource_path('skills'),
        new Skill('brand-voice', 'Use when writing customer-facing text.', 'Be friendly and brief.'),
        fn () => TeamSkill::query()->where('team_id', $this->teamId)->get()->map(
            fn ($row) => new Skill($row->name, $row->description, $row->body)
        ),
    ];
}
Enter fullscreen mode Exit fullscreen mode

The Skill constructor is (name, description, instructions, files = [], path = null). I tested the closure and the in-memory Skill with a bundled file. The database query above is only an illustration of where a closure can pull from (TeamSkill stands for an Eloquent model of your own); it is my example, not from the SDK docs.

Gotchas from testing and reading the source

  • A broken skill disappears quietly. A SKILL.md with no description, or with no --- frontmatter at all, was simply skipped. No error. If a skill never shows up, print the tool's description and check the list.
  • Only one folder level is scanned. In the source, the tool looks for skills/*/SKILL.md, so a skill nested two folders deep would not be found. I did not test that case.
  • Duplicate names: the first source wins. With two sources that define the same skill name, the earlier one in the array was used. Name your skills uniquely.
  • Declaring the tool by hand is allowed. If the agent has both skills() and its own new LoadSkill([...]) in tools(), the SDK merges them into one tool and logs a warning, because providers reject two tools with the same name.

Built-in safety limits

I tried to read files the model should never get. All were refused with a plain message:

Request Result
../shipping/SKILL.md (another skill) File is not bundled with the skill
../../run.php (outside the folder) File is not bundled with the skill
A 300 KB text file File is too large to read inline (limit is 256 KB)
A binary file File appears to be binary and cannot be read as text
A skill name that does not exist Skill does not exist

One thing the limits do not cover: a skill is text that the model will follow. Treat skill files like code, and be careful with closures that load skills from user-editable content, because anyone who can edit that text can steer your agent.

Also in 1.1: the upgrade note you should not skip

The release also adds Cohere text generation, a MoveFile tool, approval for built-in tools, and a fix so failover skips provider tools the fallback provider does not support. But the change that can surprise you is the default models. I compared the source of 1.0.1 and 1.1.0: the Anthropic default moved from claude-sonnet-5 to claude-sonnet-5-5, and the Gemini default from gemini-3.6-flash to gemini-3.8-flash. If you never choose a model, your app changes model when you upgrade. To keep control, pass a model explicitly:

(new SupportAgent)->prompt('Hello', model: 'claude-sonnet-5');
Enter fullscreen mode Exit fullscreen mode

The providers read models.text.default from their entry in config/ai.php, so you can also set a default model there. I read that in the source and did not run it.

Frequently asked questions

When should I use a skill instead of instructions()?

Keep the short, always-relevant rules in instructions(). Move topic-specific material (a policy, a procedure, a long style guide) into skills so it only costs tokens when it is needed.

Is this the latest version?

No. 1.3.0 is the newest tag I found. The skills code (LoadSkill, Skill and HasSkills) is identical between 1.1.0 and 1.3.0, so everything here applies to both.

Will it work with any model?

Skills are delivered through a normal tool call, so the model and provider you use need to support tool calling. I did not test with a live model.

References


Originally published on DEV Talk.

Top comments (0)