Overhaul the landing page with a modern, section-based layout:
- Hero slider with 3 rotating slides (Agent, Symfony, MCP) and progress bar
- Component Architecture section with layered SVG diagram
- Features section with 10 tabbed code examples
- Third-party integration bridges logo grid
- Demos section with setup steps and demo cards
- MCP SDK and Symfony Mate sections
- Sticky navbar with glassmorphism effect and Bootstrap tooltips
- Redesigned "Get Involved & Get Support" CTA section
- Full light/dark theme support with CSS variables
- Stimulus controllers for hero slider, feature tabs, and clipboard
- AOS scroll animations
- Subtle gradient backgrounds for secondary sections
This PR was squashed before being merged into the main branch.
Discussion
----------
[AI Bundle][Profiler] Fix all tools listing duplicates for each agent
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
If one is registering multiple agents the tools listing in the profiler is getting full of duplicates. So, for example, there is a `search_entries` tool and a `entry_detail` tool but you have two different agents and both get all tools, then the "Tools" section in the profiler which should just be a list of all tools available shows each of these tools in double.
I first deduplicated by taking the execution class and method as a unique selling point but had to take also the name into account as, with the names, it is also possible to have multiple tools with the same execution reference but just different names. That popped up as i thought about the subagent tool.
So hopefully `__name__::__class__::__method__` is unique enough for deduplication in the profiler all tools listing in any case.
Commits
-------
75077c5d [AI Bundle][Profiler] Fix all tools listing duplicates for each agent
This PR was merged into the main branch.
Discussion
----------
[Platform] Fix number constraints in `#[With]`
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| License | MIT
Fix two issues regarding number constraints / schema:
1. Allow floats
2. Allow negative numbers
Commits
-------
7b485923 [Platform] Fix number constraints in `#[With]`
This PR was squashed before being merged into the main branch.
Discussion
----------
[Platform][Generic][Scaleway] Fix tool call without arguments
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no <!-- please update src/**/CHANGELOG.md files -->
| Docs? | no <!-- required for new features -->
| Issues | None <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License | MIT
When calling a tool on Scaleway (extends Generic, the `arguments` array may not be included in the results, which causes problems when converting the result with `ResultConverter`.
This PR fixes the issue by checking that the array exists before retrieving its content.
Linked to #1649 (closed - merge conflicts)
Commits
-------
59601c0b [Platform][Generic][Scaleway] Fix tool call without arguments
This PR was squashed before being merged into the main branch.
Discussion
----------
[Agent] Fix dispatch of multiple tool instances of the same class
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| Issues | Fix#1657
| License | MIT
When multiple instances of the same class are registered as separate tools (e.g. two `Subagent` instances wrapping different agents), `Toolbox` would always dispatch to the first matching instance since it resolved executables by class name.
This PR fixes the issue by:
- **`MemoryToolFactory`**: Keys tool registrations by `spl_object_id` when objects are passed, allowing per-instance lookups. Builds `Tool` objects directly with `ExecutionReference` instead of going through `AsTool`/`convertAttribute`.
- **`Toolbox`**: Tries instance-specific lookup via `spl_object_id` first, falls back to class-based lookup. Maintains an `$instanceMap` to dispatch tool calls to the correct instance.
- **Removes `AbstractToolFactory`**: Inlines its logic into `ReflectionToolFactory`, since `MemoryToolFactory` no longer needs it.
- **Updates AI Bundle DI config** to reflect the removal of the abstract factory service.
Replaces #1658 1658
Commits
-------
fe195ea1 [Agent] Fix dispatch of multiple tool instances of the same class
This PR was merged into the main branch.
Discussion
----------
[Docs] Add docs-check Skill
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
<img width="1645" height="1011" alt="image" src="https://github.com/user-attachments/assets/b6a44f77-a3e2-4abb-83f1-40d4314c9cce" />
Commits
-------
10c724fc Add docs-check Skill
This PR was merged into the main branch.
Discussion
----------
Convert run-examples workflow to manual trigger
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
Replace label-based `pull_request_target` trigger with `workflow_dispatch` for the run-examples workflow, allowing it to be triggered manually from the Actions tab.
Commits
-------
fac01b75 Convert run-examples workflow to manual trigger
This PR was merged into the main branch.
Discussion
----------
Drop on push for pipeline workflows
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
This should lower the pressure on fork repos and only focus on PRs, right? 🤔
Commits
-------
992eee8f Drop on push for pipeline workflows
This PR was merged into the main branch.
Discussion
----------
[Platform][Scaleway] Add Qwen 3-embedding and Qwen 3.5
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no <!-- please update src/**/CHANGELOG.md files -->
| Docs? | no <!-- required for new features -->
| Issues | N/A
| License | MIT
Added Qwen 3 Embedding and Qwen 3.5 models for Scaleway platform.
See [Supported models](https://www.scaleway.com/en/docs/generative-apis/reference-content/supported-models/) page.
Commits
-------
7151329a Update Scaleway model catalog
This PR was merged into the main branch.
Discussion
----------
Fix broken GitHub link in website footer
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues | --
| License | MIT
Commits
-------
f66e717b Fix broken GitHub link in website footer
This PR was squashed before being merged into the main branch.
Discussion
----------
[Mate] Add Codex wrappers and refresh agent instructions on discover
| Q | A |
| ------------- | --- |
| Bug fix? | yes |
| New feature? | yes |
| Docs? | yes |
| Issues | n/a (no related issue) |
| License | MIT |
## Description
This PR improves Symfony AI Mate integration for Codex and keeps agent instructions in sync with extension discovery.
### What changed
- mate discover now also refreshes agent instruction artifacts:
- updates mate/AGENT_INSTRUCTIONS.md
- updates a managed AI Mate section in AGENTS.md
- mate init now scaffolds all integration artifacts (without running discover):
- keeps mcp.json + .mcp.json behavior
- adds Codex runtime wrappers:
- bin/codex (macOS/Linux)
- bin/codex.bat (Windows)
- adds mate/AGENT_INSTRUCTIONS.md template
- updates AGENTS.md managed section from current instruction file
- prints explicit next step to run vendor/bin/mate discover
- extracted extension sync logic to ExtensionConfigSynchronizer
- added AgentInstructionsMaterializer to centralize writing:
- mate/AGENT_INSTRUCTIONS.md
- managed block in AGENTS.md
- extended AgentInstructionsAggregator with aggregateForExtensions(...) to support fresh discovered maps and avoid stale container state
- updated Mate docs and changelog accordingly
## Usage
vendor/bin/mate init
vendor/bin/mate discover
./bin/codex
discover is now the command that refreshes both extension config and instruction artifacts.
Commits
-------
7362bb22 [Mate] Add Codex wrappers and refresh agent instructions on discover
This PR was merged into the main branch.
Discussion
----------
[Store] Split query string into words for TextQuery and HybridQuery in Retriever
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| Issues | -
| License | MIT
The `Retriever` was passing the full query string as a single text to `TextQuery` and `HybridQuery`. This makes little sense for keyword-based matching — stores use the texts with OR logic, so the query should be split into individual words to allow each term to be matched independently.
`explode(' ', $query)` is now used when constructing both `TextQuery` and `HybridQuery`, and the tests have been updated to assert that `getTexts()` returns the expected word array.
Commits
-------
0f74cee4 [Store] Split query string into words for TextQuery and HybridQuery in Retriever
This PR was merged into the main branch.
Discussion
----------
[Platform] Add `asFile()` method to `BinaryResult` and `DeferredResult`
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | no
| Issues |
| License | MIT
Rather a DX gimmick, but consistent
Commits
-------
8d246115 Add `asFile()` method to `BinaryResult` and `DeferredResult`
This PR was merged into the main branch.
Discussion
----------
[Platform] Generate JSON schema using Validator metadata
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | yes
| License | MIT
Generate JSON schema for structured output / tool calls using Validator metadata. This is convenient as the same metadata/attributes can be used for validating the structure in PHP.
Commits
-------
fc8952a2 [Platform] Generate JSON schema using Validator metadata
This PR was merged into the main branch.
Discussion
----------
[Platform][Ollama] Replace `ModelCatalog` by `OllamaApiCatalog`
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | no
| Issues | --
| License | MIT
Time to remove hard-coded catalog when possible, first target: `Ollama`
Commits
-------
b59aa9c0 refactor(ollama): remove ModelCatalog
This PR was squashed before being merged into the main branch.
Discussion
----------
[Agent] Add ToolCallRequested event for human-in-the-loop tool confirmation
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | yes
| Issues |
| License | MIT
## Description
Adds a lightweight `ToolCallRequested` event dispatched before each tool execution in the Toolbox. This event allows listeners to:
- **Deny** a tool call with a reason (`$event->deny('...')`)
- **Replace** the result to skip actual execution (`$event->setResult(...)`)
- **Allow** by doing nothing
This is the minimal building block for implementing human-in-the-loop confirmation patterns without shipping a full confirmation framework in the library.
### What's included
- `ToolCallRequested` event implementing `StoppableEventInterface`
- Integration in `Toolbox::execute()` to dispatch and handle the event
- Unit tests for the event and updated event dispatcher tests
- Simple CLI example in `examples/toolbox/confirmation.php`
- Cookbook article (`docs/cookbook/human-in-the-loop.rst`) outlining how to build policies, confirmation handlers, and decision caching on top of the event
- Updated component docs and changelog
Commits
-------
c476ed32 [Agent] Add ToolCallRequested event for human-in-the-loop tool confirmation
This PR was merged into the main branch.
Discussion
----------
[Platform][Store] Add features of #1778 and #1763 to changelog
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
Follows #1778 and #1763
Commits
-------
71459ad9 Add features of #1778 and #1763 to changelog
This PR was merged into the main branch.
Discussion
----------
[Platform][Anthropic] Add prompt caching for tool definitions
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Tickets | -
| License | MIT
## Summary
This PR adds automatic prompt caching (`cache_control`) to tool definitions in the Anthropic `ModelClient`, complementing the existing caching for system
prompts and user messages.
### Problem
Currently, `injectCacheControl()` only sets `cache_control` on the last user message. Tool definitions — which are typically **identical across all requests** —
are not cached independently. This means they are re-processed as regular input tokens on every request, even though their content never changes.
### Solution
Add `cache_control` to the last tool definition, creating an additional cache breakpoint:
System (breakpoint 1) → Tools (breakpoint 2) → Messages (breakpoint 3)
This allows the prefix "system + tools" to be cached and reused independently of the messages, which change with every request.
### Details
- New private method `injectToolsCacheControl()` mirrors the pattern of the existing `injectCacheControl()`
- Respects the existing `$cacheRetention` setting (`none` / `short` / `long`)
- No new configuration needed — follows the same caching strategy already in place
- Tool definitions are an ideal caching target: they are static across requests and can be substantial in size (descriptions + JSON schemas)
### Cost impact
With Anthropic's pricing:
- `cache_creation`: 1.25× input price (one-time per cache entry)
- `cache_read`: 0.1× input price (every subsequent request)
Since tool definitions don't change, the cache entry is created once and read on every subsequent request within the TTL — a significant cost reduction for
tool-heavy agents.
Commits
-------
d8b1d368 [Platform][Anthropic] Add prompt caching for tool definitions
This PR was merged into the main branch.
Discussion
----------
[Platform] Fix ClaudeCode ModelClientTest to work on macOS
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no <!-- please update src/**/CHANGELOG.md files -->
| Docs? | no <!-- required for new features -->
| Issues | n/a
| License | MIT
I'm trying to run tests more on my machine instead of waiting for CI, so this fix would help me 😇
Some tests hardcoded `/usr/bin/echo`, but it should be `/bin/echo` on macOS.
Commits
-------
3945db4d [Platform] Fix ClaudeCode ModelClientTest to work on macOS
This PR was merged into the main branch.
Discussion
----------
[Store] Introduce batch processing in `DistanceCalculator`
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | yes
| Issues | --
| License | MIT
Following #1770, local stores might be used to store / retrieve vectors, problem is, the current implementation perform the sorting strategy through the whole dataset, this PR aims to introduce a "batch and reduce" approach, `VectorDocument`s are handled per batch (default size to `100`) and returned in smaller size if `maxItems` is set.
The implementation is inspired by https://x.com/JeffDean/status/1997854093239595503.
Commits
-------
293df7d9 feat(store): allow to sort documents as batches
This PR was squashed before being merged into the main branch.
Discussion
----------
[Store] Skip missing toctree entries gracefully
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | no
| Issues |
| License | MIT
## Summary
Skip missing toctree entries with a log warning instead of throwing. The previous strict behavior is available via the `throwOnMissingEntry` constructor parameter.
Commits
-------
b1f6e8a1 [Store] Skip missing toctree entries gracefully
This PR was merged into the main branch.
Discussion
----------
[Examples] Store SQLite database in .sqlite directory
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
Move the SQLite vector database from `var/` to `.sqlite/` with auto-creation of the directory. Keeps generated files in a gitignored hidden directory.
Commits
-------
beb496fa [Examples] Store SQLite database in .sqlite directory
Move the SQLite vector database from var/ to .sqlite/ and ensure the
directory is created automatically. This keeps generated database files
in a gitignored hidden directory consistent with other dot-prefixed
data directories.
This PR was squashed before being merged into the main branch.
Discussion
----------
[Store] Add SQLite store bridge
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | yes
| Issues | -
| License | MIT
## Summary
Adds a SQLite store bridge — a lightweight, zero-infrastructure vector store using PHP-side distance calculation via `DistanceCalculator` and SQLite FTS5 for full-text search. Supports `VectorQuery`, `TextQuery`, and `HybridQuery`.
Includes store implementation, unit/integration tests, example, documentation, and full package scaffolding. AI Bundle integration to follow separately.
Commits
-------
e04f211c [Store] Add SQLite store bridge
This PR was merged into the main branch.
Discussion
----------
[Platform][Store] Consistently use symfony/event-dispatcher-contracts
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| Docs? | no
| Issues |
| License | MIT
Always use `symfony/event-dispatcher-contracts`.
Commits
-------
91b38e10 Consistently use symfony/event-dispatcher-contracts
This PR was merged into the main branch.
Discussion
----------
[Store] Fix RstToctreeLoader trailing-slash toctree entry resolution
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Docs? | no
| Issues | Fix#1771
| License | MIT
## Summary
Trailing-slash toctree entries like `components/` are valid Sphinx syntax and resolve to `components/index.rst`. The
loader now handles this convention instead of producing the invalid path `components/.rst`.
Commits
-------
1bd2a72e [Store] Fix RstToctreeLoader trailing-slash toctree entry resolution
This PR was merged into the main branch.
Discussion
----------
[Platform][Mistral] Add token usage extraction for embeddings
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| Docs? | no
| Issues | -
| License | MIT
## Description
This PR adds token usage extraction support for Mistral embeddings — the first embedding bridge to support this.
### Changes
1. **`Mistral\Embeddings\TokenUsageExtractor`** — New class implementing `TokenUsageExtractorInterface`. Extracts `prompt_tokens`, `total_tokens`, and rate limit headers (`x-ratelimit-limit-tokens-minute`, `x-ratelimit-limit-tokens-month`) from Mistral embedding responses. No `completionTokens` since embeddings don't produce completions.
2. **`Mistral\Embeddings\ResultConverter`** — `getTokenUsageExtractor()` now returns the new extractor instead of `null`.
3. **Updated Mistral embeddings example** to display token usage.
### Usage
```php
$result = $platform->invoke('mistral-embed', 'Some text to embed');
$tokenUsage = $result->getMetadata()->get('token_usage');
$tokenUsage->getPromptTokens(); // e.g. 15
$tokenUsage->getTotalTokens(); // e.g. 15
```
Commits
-------
81caade2 [Platform][Mistral] Add token usage extraction for embeddings