Kai Ole Hartwig

sylius-agent-ready — a shop that agents can use.

A Sylius shop is built for people with browsers. An agent arriving there finds no way to learn what is for sale, no machine-readable price and no way to identify itself. Seventeen MIT-licensed bundles close that gap — one package per protocol, each usable on its own.

What an agent finds in the shop

With sylius-agent-ready

A product feed at SKU level with the price in the smallest unit and availability. Content Signals that state what is allowed. OAuth 2.1 with dynamic client registration — an agent identifies itself before it asks.

Until now

An HTML catalogue from which prices can only be extracted by scraping. No statement on whether the content may be indexed or used for training. No registration, no identity — every request is anonymous and indistinguishable from the next bot.

The four groups

MCP

mcp · webmcp

Tools instead of documents. The Server Card per SEP-1649, so that an agent knows the transport and the tool surface before it connects — and WebMCP, which offers the same actions in the customer's browser.

Commerce protocols

acp · ucp · mpp · x402

How an agent transacts. ACP discovery with an SKU-level product feed, the UCP profile, an OpenAPI document with x-payment-info and x402 middleware that answers a data route with HTTP 402 when it has not been paid for.

Agent authentication

mcp-oauth · auth-md · web-bot-auth

How an agent identifies itself. OAuth 2.1 with dynamic client registration and mandatory PKCE, plus the RFC 8414 and RFC 9728 metadata. /auth.md describes the same path in prose — from the same source, so that text and metadata do not drift apart.

Discovery

robots-txt · llms-txt · markdown · api-catalog · agent-skills · a2a

How an agent finds and understands the shop in the first place. robots.txt with AI crawlers named individually and Content Signals, llms.txt as a map rather than a catalogue, Markdown negotiation via Accept, the RFC 9727 API catalogue together with Link headers, the Agent Skills index and the A2A Agent Card.

One package per protocol. Usable on its own. No catch-all bundle.

Sylius: 2.0+ · PHP: 8.2+ · Licence: MIT · Version: 1.0.0

If you want everything, take the metapackage koh/sylius-agent-ready. If you only need llms.txt, install just that — and you will not pull in crypto dependencies you never wanted.

Discovery is free, data may cost

The x402 middleware answers a route with HTTP 402 and the payment requirements an agent can meet. It is off by default — installing a bundle must not start asking for money.

Once it is switched on, a boundary applies that lives in the code and not in the documentation: only data routes are gated. Never the storefront, never the checkout, and explicitly never the discovery documents. A /.well-known/* behind a paywall does not make a shop profitable, it makes it invisible.

An agent with a valid OAuth token passes through without paying. Both routes are stated in the same 402 response — a known agent pays by contract, an unknown one per request.

The purchase stays with the human wherever the law requires it

The ACP bundle knows two states. By default it declares the catalogue and withholds the checkout — because an agent that reads checkout in the capabilities will try to buy through the API.

For a shop with age-restricted products that is not an option: the purchase has to happen in a visible browser session where age can be verified. Every feed entry therefore carries age_restriction, so that an agent does not mistake a restricted product for ordinary goods.

This is not a gap in the implementation. ACP and UCP both provide a checkout session handoff for exactly this case — the agent prepares, the human completes. If your range carries no such requirements, you enable the checkout with one line of configuration.

Seventeen packages that do not know each other

One package per protocol means the API catalogue has to know what the others offer — without knowing them. A foundation package solves that: koh/sylius-agent-contracts. It ships no endpoint of its own, only interfaces, registries and a request context.

A class that implements one of these interfaces is registered automatically across the container — including from your own App\ namespace, without any wiring. If you want your magazine in llms.txt, you write twenty-five lines and you are done.

The effect shows when you remove something: if a package is not installed, its entry disappears everywhere at once — from llms.txt, from the API catalogue, from the Link headers. There is no place where a capability lingers that nobody serves any more.

Installing is not enough

composer require koh/sylius-agent-ready

 

A metapackage cannot register bundles, import routes or set a firewall entry. Three steps stay manual, and the shop is not agent-ready until all three are done. The most important one is the third.

The firewall exception has to sit above the Sylius firewalls. Sylius' shop_regex is a catch-all and matches /.well-known/… as well — and that firewall is stateful. Without an exception every crawler request starts a session, and every response carries Set-Cookie: not cacheable, for documents whose entire purpose is to come from a shared cache. An access_control entry does not help — it only takes effect after a firewall has already matched.

And: delete public/robots.txt. The web server answers it from disk before Symfony is asked at all, and shadows the dynamic route silently.

Whether everything is in place is answered by a command that actually calls every announced endpoint:

 

bin/console koh:agent:check

 

It finds the fault no unit test sees, because both halves are correct in themselves: a bundle announces an endpoint, llms.txt and the API catalogue dutifully advertise it — and the route was never imported. Agents run into a 404 while every document looks correct.

Source code & documentation

Security reports

CVD · CSAF 2.0

Please do not open a public issue. Coordinated vulnerability disclosure via security@ole-hartwig.eu; advisories are published as CSAF 2.0.

CSAF channel
Security reports

Licence & support

MIT licence · semantic versioning

MIT. Support windows follow the published end-of-life policy. Every package ships a README, a CHANGELOG and a decommissioning guide — how to get rid of it again is documented just as well as the installation.

Composer package

MIT · Sylius 2.0+ · PHP 8.2+

composer require koh/sylius-agent-ready

All seventeen packages are built, tested and released under MIT. Public distribution via Packagist is being prepared (coming soon) — until then they run from the private Composer registry.

A shop that agents should find?

The packages run without me — MIT-licensed, documented, with tests. If you want to use them yourself, you need nothing beyond the documentation.

If you want support — integration into an existing shop, a protocol of your own, or the question of which discovery surface makes legal sense for your range at all — get in touch.