neuron-core / agent-skills
Agent Skills toolkit with pluggable storage for Neuron AI.
Requires
- php: ^8.1
- neuron-core/neuron-ai: ^4.0
- symfony/polyfill-intl-normalizer: ^1.31
- symfony/polyfill-mbstring: ^1.31
- symfony/yaml: ^6.4 || ^7.0 || ^8.0
Requires (Dev)
- ext-pdo: *
- ext-pdo_sqlite: *
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^10.5
- symfony/dotenv: ^6.4
Suggests
- ext-pdo: Required to use DatabaseSkillStorage, together with the PDO driver for your database.
Provides
None
Conflicts
None
Replaces
None
README
Important
Get early access to new features, exclusive tutorials, and expert tips for building AI agents in PHP. Join a community of PHP developers pioneering the future of AI development. Subscribe to the newsletter
Before moving on, support the Neuron AI community giving a GitHub star ⭐️. Thank you!
Add Agent Skills to your Neuron AI
agents with SkillToolkit. Combine your own skills with community packages and
make them available to the agent through a single toolkit.
The library handles skill discovery and provides tools for loading instructions and supporting resources when needed. It follows the open Agent Skills specification and supports local directories, PDO databases and custom storage.
Installation
Requires PHP 8.1+.
| Agent Skills | Neuron AI |
|---|---|
| 2.x (current) | 4.x |
| 1.x | 4.x |
| 0.x | 3.x |
composer require neuron-core/agent-skills
Quick Start
Find community skills on skills.sh and install one from your application's root:
npx skills add juliusbrussee/caveman --skill caveman --agent universal --yes
The Skills CLI requires Node.js/npm and
installs caveman into .agents/skills. Create an agent and register that
directory, replacing your-api-key with your OpenAI API key:
use NeuronAI\Agent\Agent; use NeuronAI\Chat\Messages\UserMessage; use NeuronAI\Providers\OpenAI\OpenAI; use NeuronAI\AgentSkills\Storage\FileSystemSkillStorage; use NeuronAI\AgentSkills\Tools\SkillToolkit; $toolkit = SkillToolkit::make() ->fromStorage(new FileSystemSkillStorage(__DIR__.'/.agents/skills')); $agent = Agent::make() ->setThreadId('quick-start') ->setAiProvider(new OpenAI(key: 'your-api-key', model: 'gpt-5.4-mini')) ->addTool($toolkit); $response = $agent->chat(new UserMessage( 'Use caveman skill to explain how the universe works.', )); echo $response->getMessage()->getContent(); // Actual response (excerpt): // Cosmic history: big bang expansion. Early hot plasma cooled; atoms formed. // Gravity pulled gas into stars, stars forged heavier elements. Supernovae // spread elements; mergers build galaxies.
How Skills Work
The agent starts with only the name and description of each skill. When a skill is relevant, it loads the full instructions on demand:
| Tool | Purpose |
|---|---|
skill |
Load a skill's instructions by its declared name. |
skill_resource |
Read one supporting file, such as references/guide.md, from that skill. |
skill_script_prepare |
Make the skill's files available in a local directory before running its scripts. |
Skills can include scripts. The toolkit does not execute them: register an
execution tool such as Neuron's BashTool alongside it.
use NeuronAI\Tools\Toolkits\FileSystem\BashTool; $agent = Agent::make() ->setAiProvider(new OpenAI(key: 'your-api-key', model: 'gpt-5.4-mini')) ->addTool($toolkit) // Loads skills and prepares their files. ->addTool(new BashTool()); // Runs the skill scripts.
Filesystem skills run from their original directory. Skills from other storages
are copied to a new directory under sys_get_temp_dir(); the toolkit does not
delete these copies.
Multiple Sources
Pass several storages to combine bundled skills, CLI-installed skills and database skills:
use NeuronAI\AgentSkills\Storage\DatabaseSkillStorage; $toolkit = SkillToolkit::make()->fromStorage( new FileSystemSkillStorage(__DIR__.'/skills'), new FileSystemSkillStorage(__DIR__.'/.agents/skills'), new DatabaseSkillStorage(new PDO('sqlite:'.__DIR__.'/skills.sqlite')), );
If two skills declare the same name, the agent gets the one from the first storage. Its instructions and files always come from that source, with no fallback to another skill with the same name.
Skills are discovered on first use and then cached. Recreate the toolkit to pick up newly added skills.
Database Storage
DatabaseSkillStorage reads skills from an existing PDO connection. Each row
stores one file of a skill; the complete skill document goes at path SKILL.md.
You create and populate the table, for example:
CREATE TABLE skills ( skill_identifier VARCHAR(255) NOT NULL, path VARCHAR(255) NOT NULL, content TEXT NOT NULL, UNIQUE (skill_identifier, path) ); INSERT INTO skills VALUES ('caveman', 'SKILL.md', '--- name: caveman description: Answer in terse caveman speech. --- Use short words. Drop articles.'), ('caveman', 'references/examples.md', 'Big rock fall. Many dino gone.');
$storage = new DatabaseSkillStorage($pdo); // table "skills" $archive = new DatabaseSkillStorage($pdo, table: 'archived_skills');
skill_identifiergroups the rows of one skill. It may differ from thenamedeclared inSKILL.md.skill_identifierandpathmust be compared case-sensitively. SQLite and PostgreSQL do this by default; on MySQL, use a binary collation such asutf8mb4_bin.- The adapter only reads: it never creates or migrates tables. Integration tests run on SQLite.
Accessing Skills Directly
Share a SkillRepository between the toolkit and other features, such as slash
commands or a skill picker:
use NeuronAI\AgentSkills\SkillRepository; $skills = new SkillRepository( new FileSystemSkillStorage(__DIR__.'/.agents/skills'), ); $agent->addTool(new SkillToolkit($skills)); foreach ($skills->catalog() as $skill) { echo $skill->name().': '.$skill->description().PHP_EOL; } $skill = $skills->getByName('caveman'); // Throws if unknown. $skill->loadInstructions(); // Body without YAML frontmatter. $skill->loadFrontmatter(); // Parsed metadata as stdClass. $skill->resource('references/guide.md')->load(); foreach ($skill->resources() as $resource) { echo $resource->path().PHP_EOL; }
Other frontmatter fields are preserved and available through loadFrontmatter().
Custom Storage
Implement SkillStorageInterface to
load skills from another backend:
interface SkillStorageInterface { /** @return list<string> Skill identifiers in this storage. */ public function list(): array; /** @return list<string> Relative paths of every file, including SKILL.md. */ public function resources(string $skillIdentifier): array; public function read(string $skillIdentifier, string $path): string; }
Throw RuntimeException for missing or unreadable files. If the files are
already on the local disk, also implement
LocalSkillStorageInterface so
scripts run from the original directory instead of a temporary copy.
StoragePaths helps validate identifiers and normalize
paths.
Error Handling
Invalid or unreadable skills are skipped; inspect $skills->diagnostics() to
see why. Tools report read failures to the agent. When accessing skills
directly, catch RuntimeException.
Runnable Examples
The examples include interactive demos with filesystem, database and mixed storages, including skills that run scripts.
Contributing
Report bugs and propose changes through GitHub Issues
and pull requests. Development requires PDO and pdo_sqlite:
composer install
composer test
composer analyse
Neither command requires an API key.
License
MIT.
