koh / sylius-acp
Agentic Commerce Protocol discovery for Sylius: /.well-known/acp.json and a read-only product feed for agents.
Requires
- php: ^8.3
- koh/sylius-agent-contracts: ^1.1
- sylius/sylius: ^2.2.9 || ^2.3.0
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/routing: ^7.4 || ^8.0
- symfony/serializer: ^7.4 || ^8.0
Requires (Dev)
- doctrine/collections: ^2.6.0
- koh/dev-sylius: ^1.0
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan: ^2.3.1
- phpstan/phpstan-doctrine: ^2.0.28
- phpunit/phpunit: ^11.5.57
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- v1.1.40
- v1.1.39
- v1.1.38
- v1.1.37
- v1.1.36
- v1.1.35
- v1.1.34
- v1.1.33
- v1.1.32
- v1.1.31
- v1.1.30
- v1.1.29
- v1.1.28
- v1.1.27
- v1.1.26
- v1.1.25
- v1.1.24
- v1.1.23
- v1.1.22
- v1.1.21
- v1.1.20
- v1.1.19
- v1.1.18
- v1.1.17
- v1.1.16
- v1.1.15
- v1.1.14
- v1.1.13
- v1.1.12
- v1.1.11
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- dev-main / 1.0.x-dev
- v1.0.0
This package is auto-updated.
Last update: 2026-10-18 17:39:05 UTC
README
koh/sylius-acp
Agentic Commerce Protocol (ACP) discovery for
Sylius: a discovery document at /.well-known/acp.json and a read-only,
SKU-level product feed agents can browse.
- Discovery document — protocol version, API base URL, transports and the channel's currency and locales, per channel.
- Product feed — one entry per enabled variant, with price in minor units, currency, availability and an optional age restriction.
- Read-only by default — checkout is not declared unless you switch it on.
- Registered as a skill — the catalogue shows up in the A2A card, the
agent-skills index and the MCP server card of the other
kohbundles without extra configuration.
Requires PHP 8.3 or later and Sylius 2.2 or 2.3.
Install
composer require koh/sylius-acp
Register the bundle and the shared contracts bundle it builds on:
// config/bundles.php return [ // … Koh\SyliusAgentContracts\KohSyliusAgentContractsBundle::class => ['all' => true], Koh\SyliusAcp\KohSyliusAcpBundle::class => ['all' => true], ];
Import the routes:
# config/routes/koh_agent.yaml koh_acp: resource: '@KohSyliusAcpBundle/config/routes.php'
Clear the cache and check that both endpoints answer:
bin/console cache:clear
curl -s https://shop.example.com/.well-known/acp.json
curl -s 'https://shop.example.com/api/agent/feed?limit=2'
Configure
Everything has a default; the file is only needed to change one:
# config/packages/koh_acp.yaml koh_acp: version: '2026-01-30' # ACP version announced in the discovery document api_base: '/api/agent' # advertised as api_base_url checkout: false # declare the checkout service age_restriction: ~ # minimum age carried on every feed item feed: default_limit: 100 max_limit: 500
api_baseis announced, not routed. The feed route is fixed at/api/agent/feed; if you changeapi_base, add a route for{api_base}/feedpointing atKoh\SyliusAcp\Controller\ProductFeedController.checkoutstays off unless the shop really completes purchases through the API. An agent that findscheckoutin the capabilities will try to buy.age_restrictionbelongs on every age-restricted catalogue. A feed that omits it invites an agent to treat restricted items as ordinary stock.
Output
GET /.well-known/acp.json:
{
"protocol": {
"name": "acp",
"version": "2026-01-30",
"supported_versions": ["2026-01-30"],
"documentation_url": "https://agenticcommerce.dev"
},
"api_base_url": "https://shop.example.com/api/agent",
"transports": ["rest"],
"capabilities": {
"services": ["catalog"],
"supported_currencies": ["eur"],
"supported_locales": ["en-US", "de-DE"]
}
}
GET /api/agent/feed?page=1&limit=2:
{
"items": [
{
"id": "T_SHIRT_M",
"item_group_id": "T_SHIRT",
"title": "T-shirt, size M",
"description": "Organic cotton, regular fit.",
"link": "https://shop.example.com/en_US/products/t-shirt",
"availability": "in_stock",
"condition": "new",
"price": "1990",
"price_currency": "EUR"
}
],
"page": 1,
"limit": 2,
"count": 1
}
limit is clamped to 1…max_limit and page to at least 1, so a crafted
query string cannot pull the whole catalogue in one request. limit counts
products; count is the number of variants returned. Descriptions are plain
text, at most 500 characters.
q narrows the feed to products whose name contains the term (in the
channel's locale, enabled and in this channel only; at most 100 characters).
Without it the feed lists the channel's latest products.
The discovery document is cached for an hour, the feed for 15 minutes.
Decommission
Remove the composer require, the config/bundles.php entry, the route import
and config/packages/koh_acp.yaml. No database table, no cache pool.
Security
Report vulnerabilities privately — see SECURITY.md. Advisories are published as CSAF 2.0 at https://ole-hartwig.eu/.well-known/csaf/.
The family threat model, covering this package, is at https://github.com/ohartwig/sylius-agent-ready/blob/main/docs/threat-model.md.
Licence
MIT — see LICENSE.