This file provides guidance to AI agents when working with code in this repository.
This is the Symfony AI monorepo containing multiple components and bundles that integrate AI capabilities into PHP applications. The project is organized as a collection of independent packages under the src/ directory, each with their own composer.json, tests, and dependencies.
- Platform (
src/platform/): Unified interface to AI platforms (OpenAI, Anthropic, Azure, Gemini, VertexAI, etc.) - Agent (
src/agent/): Framework for building AI agents that interact with users and perform tasks - Chat (
src/chat/): Chat interface components for building conversational AI applications - Store (
src/store/): Data storage abstraction with indexing and retrieval for vector databases - Mate (
src/mate/): AI-powered coding assistant for PHP development
Each core component has bridges in src/<component>/src/Bridge/ that provide integrations with specific third-party services. Bridges are dedicated Composer packages with their own dependencies and can be installed independently.
- AI Bundle (
src/ai-bundle/): Symfony integration for Platform, Store, and Agent components - MCP Bundle (
src/mcp-bundle/): Symfony integration for official MCP SDK
- Examples (
examples/): Standalone examples demonstrating component usage across different AI platforms - Demo (
demo/): Full Symfony web application showcasing components working together - Fixtures (
fixtures/): Shared test fixtures for multi-modal testing (images, audio, PDFs)
Each component has its own test suite. Run tests for specific components:
# Platform component
cd src/platform && vendor/bin/phpunit
# Agent component
cd src/agent && vendor/bin/phpunit
# AI Bundle
cd src/ai-bundle && vendor/bin/phpunit
# Demo application
cd demo && vendor/bin/phpunitThe project uses PHP CS Fixer with Symfony coding standards. Always run from the repository root:
# Fix code style issues
vendor/bin/php-cs-fixer fix
# Fix specific directories
vendor/bin/php-cs-fixer fix src/platform/Static analysis with PHPStan (component-specific):
cd src/platform && vendor/bin/phpstan analyseAfter adding or changing any RST files in docs/, always run the doctor-rst validator from the repository root:
./doctor-rstThis uses Docker (oskarstark/doctor-rst) to validate RST documentation files and catch formatting issues.
The RST files in docs/cookbook/ are the single source of truth for the cookbook on ai.symfony.com. After adding, removing, or changing any docs/cookbook/*.rst file — including the .. card: front matter or the index.rst toctree order — regenerate the committed website artifacts:
cd ai.symfony.com && php bin/console app:cookbook:buildThis rebuilds ai.symfony.com/config/cookbook.json and the HTML fragments in ai.symfony.com/templates/cookbook/content/ from the RST. Always commit the regenerated artifacts together with the RST changes: production (Upsun) ships only the ai.symfony.com/ directory and cannot run the generator, so stale artifacts would ship outdated cookbook content.
Use the ./link script to symlink local development versions:
# Link components to external project
./link /path/to/project
# Copy instead of symlink
./link --copy /path/to/project
# Rollback changes
./link --rollback /path/to/projectExamples are self-contained and can be run individually:
cd examples
php anthropic/chat.php
php openai/toolcall.phpMany examples require environment variables (see .env files in example directories).
The demo is a full Symfony application:
cd demo
composer install
symfony server:startComponents are designed to work independently but have these relationships:
- Agent depends on Platform for AI communication
- AI Bundle integrates Platform, Agent, and Store
- MCP Bundle provides official MCP SDK integration
- Store is standalone but often used with Agent for RAG applications
Each component uses:
- PHPUnit 11+ for testing framework
- Component-specific
phpunit.xml.distconfigurations - Shared fixtures in
/fixturesfor multi-modal content - MockHttpClient pattern preferred over response mocking
- Each component in
src/is a separate Composer package with its own dependencies - Components follow Symfony coding standards and use
@SymfonyPHP CS Fixer rules - The monorepo structure allows independent versioning while maintaining shared development workflow
- Do not use void return type for testcase methods
- Always run PHP-CS-Fixer to ensure proper code style
- Always add a newline at the end of the file
- Prefer $this->assert* over self::assert* in tests
- Never add Claude as co-author in the commits
- Add @author tags to newly introduced classes by the user
- Prefer classic if statements over short-circuit evaluation when possible
- Define array shapes for parameters and return types
- Use project specific exceptions instead of global exception classes like \RuntimeException, \InvalidArgumentException etc.
- NEVER mention Claude as co-author in commits
- Avoid using the
empty()function; prefer explicit checks like[] === $array,'' === $string, ornull === $value
The content under docs/ splits into distinct kinds, and confusing them is the most
common authoring mistake. The guiding axis is orientation: reference follows the
structure of the software; a cookbook recipe follows the structure of the user's
problem.
- Reference / explanation (the component docs) — describes what something is: its options, its API, the why behind a design. Organized around the shape of the code. The reader jumps in to look up a fact, not to read front-to-back. Truth and completeness matter most.
- Cookbook (
docs/cookbook/) — answers how do I achieve X. Organized around a goal the reader already has, read top-to-bottom toward a concrete working outcome. Assumes competence: it solves a real problem, it does not teach the basics. - Getting started — onboarding / learning-oriented walkthroughs belong on the docs index page of the respective component, not in the cookbook. The cookbook is for readers who already know the basics.
When deciding whether a piece belongs in the cookbook, apply these tests:
- Does it read as a journey to a concrete outcome, or is it something you'd jump into the middle of? Journey → cookbook. Lookup → component docs.
- If you strip the narrative, what's left? If it collapses into "here are the options for feature X", it is reference wearing a recipe costume — move it to the docs.
- Does it compose two or more components/features into a realistic feature (e.g. "add memory to a chatbot", "orchestrate multiple agents")? Composition belongs in the cookbook; a single-feature walkthrough is usually a doc.
- A strong recipe should ideally map to something runnable under
examples/. If there is no end artifact you could run to see it work, it is probably explanation/reference.
- Document breaking changes in the root
UPGRADE.mdfile - Format: Use version headers like
UPGRADE FROM 0.X to 0.Ywith sections per component - Include code examples showing before/after changes with diff syntax
- Every
UPGRADE.mdentry must be paired with theBC BreakPR label, and adding theBC Breaklabel requires a matchingUPGRADE.mdentry in the upcoming (unreleased) section
- Each component has its own
CHANGELOG.mdin its root directory - Add entries for new features, and deprecations under the appropriate version heading
- Format entries as bullet points starting with "Add", "Fix", "Deprecate", etc.
- Bug-fix-only PRs (
Bug fix? = yes,New feature? = no) must not modify anyCHANGELOG.md/UPGRADE.md— unless the fix is itself a BC break, in which case add theBC Breaklabel and document it inUPGRADE.md - Only add entries to the upcoming (unreleased) version section; sections already released (version
<=the latest git tag) are frozen
These conventions are enforced on every PR by .github/workflows/changelog.yaml.
- Always use the PR template from
.github/PULL_REQUEST_TEMPLATE.md - Fill in the table at the top of the PR description with appropriate values:
- Bug fix?: yes/no
- New feature?: yes/no (update CHANGELOG.md files for new features)
- Docs?: yes/no (required for new features)
- Issues: Fix #... (prefix each issue number with "Fix #")
- License: MIT
- Provide a clear description of the changes below the table