The Agent Search Contract: The Structured Answer a Machine Buyer Needs
The Agent Search Contract is the field-level specification a store must return so a machine can shop it. A person reads a result card and infers meaning from layout. An agent cannot. It needs an explicit match state, the matched variant identity, an honest count, valid facets, a stable continuation, and the authorisation that makes the request accountable.
This guide specifies those fields with concrete semantics, two illustrative request and response fixtures, and a diagnostic that maps catalogue failures to the contract field each one breaks. It is a framework and a testing protocol, not a wire format. The pillar explains why agentic commerce makes this urgent; the catalogue guide explains the data each field depends on.
A page tells a human what happened. A contract tells a machine what happened, field by field, so it can act, recover, and stay within bounds without a person in the loop.
Chapter 1 · The match-state enum
One value that decides whether an agent can trust the result
The single most important field is match_state. A human sees a results page and senses whether it is exact or a guess. An agent sees a list and assumes success unless told otherwise. The enum below gives the agent a branch point instead of a belief. Today, a typical storefront search response returns product cards built for a person, title, image, price, with no explicit match status and no resolved variant id on the result itself, so an agent has to infer both. The contract adds what the raw response omits.
| State | Means | What the agent does |
|---|---|---|
| exact | The request identifier or full constraint set resolved to one item with no relaxation. | Proceed to handoff on the matched variant without further disambiguation. |
| partial | Some constraints matched; others were absent or under-specified in the source data. | Return candidates and name the missing dimension rather than guessing a value. |
| corrected | The query contained a likely error; the system matched the intended item with stated evidence. | Surface the correction explicitly so the agent can confirm before acting. |
| relaxed | No exact match; results expanded along a declared, reversible relaxation rule. | Label the relaxation so the agent can tighten the request instead of trusting the set. |
| no_match | No item satisfied the constraints within the active catalog and market. | Return an empty set with the reason, not a fallback list that implies a match. |
no_match is a valid state, not a failure. Returning an empty set with a reason is more useful to an agent than a fallback list that implies a match it did not make.
Chapter 2 · Field-by-field semantics
Seven fields, each with a job an agent cannot infer
Each field below is shown three ways: what it is, what the agent does with it, and what breaks when it is missing or malformed. The third part is the one most specs skip, and it is the part that decides whether an agent buys the right thing or quietly fails. A field that looks optional to a person is often load-bearing to a machine.
01
query
A normalised request. Identifiers stay unparsed (SKU, barcode, MPN), attributes become typed constraints, and the market and customer context travel with the call.
What the agent does with it: Sends the identifier as one atomic token, not words. If it sends "TR4-NV-08-W" as a string, the store matches the exact SKU instead of guessing from "TR4", "NV", "08", "W" as separate terms.
What breaks without it: If the search layer tokenises the SKU, "TR4-NV-08-W" splits into fragments and matches any product containing those fragments, so the agent gets a near-miss family instead of the one item. Identifier integrity is the difference between exact and accidental match.
02
match_state
One value from the match-state enum, present on every response including no_match.
What the agent does with it: Branches on the value. exact: hand off. partial: read the named missing dimension and refine. corrected: surface the fix and confirm. relaxed: tighten the request. no_match: stop and report the reason. The state, not the count, tells the agent whether the job succeeded.
What breaks without it: Without an explicit state, the agent reads result count as success. A relaxed set of 40 looks identical to an exact set of 1, so the agent presents a guess as a fact and the shopper buys the wrong thing.
03
results[]
Each record carries product identity, the matched variant id, option values, price, availability, and the evidence that caused the match.
What the agent does with it: Reads variant_id and matched_options to confirm the exact item before acting, and reads match_evidence to know why the system chose it. The record is the unit of truth, not the product family.
What breaks without it: A parent product with the wrong selected variant is a wrong answer to a machine even when the family is right. If the result returns only the parent with a default colour, the agent adds the "navy" item to cart but the store ships "black", because the variant was never named.
04
count
An exact integer or an honestly labelled estimate, never a precise-looking number that is actually sampled.
What the agent does with it: Uses the count to decide whether to paginate and to tell the shopper how many options exist. When the count is an estimate, the agent treats it as approximate and stops paginating once it has enough candidates.
What breaks without it: An agent that trusts a count of 237 will paginate to page 10 and present items that do not exist, because the number was a sampled estimate. The shopper sees products that cannot be opened or bought.
05
facets
Valid refinement values with counts, scoped to the current result set, not the whole catalog.
What the agent does with it: Reads the facet list to choose the next refinement (colour, size, fitment) and only offers values that still have eligible items, so each turn narrows the set.
What breaks without it: A facet value with zero eligible items wastes an agent turn and can loop it into dead refinements: it picks "wide", gets zero results, picks "medium", gets zero, and never reaches the size that actually exists.
06
continuation
A cursor or offset that preserves order and the active constraint set across pages.
What the agent does with it: Follows the cursor to fetch the next slice without re-sending the query, and expects the same ordering and filters on page two as on page one.
What breaks without it: A stateless page number resets filters and re-orders results, so the agent reads a different set on page two than page one and may present the same item twice or miss the one it needs.
07
authorisation
The wallet handle and spend scope that make the request attributable and bounded.
What the agent does with it: Attaches the handle so the merchant knows who is asking and within what spend scope, then stays inside that scope. The merchant can entitle, cap, and audit the request.
What breaks without it: Without it the request is an anonymous bot: the merchant cannot attribute the buyer, cannot cap spend, and cannot tell a legitimate agent from a scraper, so the request is blocked or trusted blindly.
Chapter 2b · How the agent decides, end to end
One query, walked through every field
The seven fields are not a checklist. They are a decision path. Here is the exact-identifier job, TR4-NV-08-W, traced field by field so you can see how the agent actually uses the contract to buy the right thing.
query
Sends identifier "TR4-NV-08-W" as one token. The store matches the SKU exactly, not the words inside it.
match_state
Reads match_state: exact. Because it is exact, the agent skips refinement and goes straight to handoff.
results[]
Reads variant_id 8731 and matched_options navy / UK 8 / wide. Confirms the exact item before adding to cart.
count
Reads count: 1. One result, so no pagination and no "which one?" ambiguity.
facets
Ignores facets: with an exact match there is nothing to refine. The field is present but unused, which is correct.
continuation
Reads continuation: null. No further pages exist, so the agent stops here.
authorisation
Carries handle acme.cloudflare.pay with scope read-search, so the merchant knows who asked and what they may do.
The contract turned a guess into a procedure. Every field told the agent one thing to do or check. With all seven present, the agent buys variant 8731 and stops. With any one missing, it either guesses, loops, or buys the wrong item, and no human is in the loop to catch it.
Chapter 3 · Worked fixtures
What the contract looks like for two real jobs
The fixtures below are illustrative. They follow the identifier-to-variant handoff from the Variant Search guide: a SKU resolves to one variant and that identity survives the handoff. Replace the identifiers with your own store's real values before relying on the shape.
Exact identifier job · illustrative
{
"query": { "identifier": "TR4-NV-08-W", "market": "CA" },
"match_state": "exact",
"count": 1,
"results": [
{
"product_id": "trail-runner-4",
"variant_id": 8731,
"matched_options": { "colour": "navy", "size": "UK 8", "width": "wide" },
"price": { "amount": 15900, "currency": "CAD" },
"availability": "available",
"match_evidence": "sku TR4-NV-08-W -> variant 8731",
"handoff": "?variant=8731"
}
],
"continuation": null,
"authorisation": { "handle": "acme.cloudflare.pay", "scope": "read-search" }
}Compatibility job, partial match · illustrative
{
"query": { "compatibility": "2019 Honda Civic", "part": "cabin-air-filter" },
"match_state": "partial",
"count": 2,
"results": [
{
"product_id": "caf-19-hc",
"variant_id": 5520,
"compatibility_evidence": "fitment: 2019 Civic (confirmed)",
"price": { "amount": 1999, "currency": "USD" },
"availability": "available"
}
],
"missing_dimension": "engine_variant",
"continuation": { "cursor": "caf_2" },
"authorisation": { "handle": "acme.cloudflare.pay", "scope": "read-search" }
}Notice the partial match names its missing dimension. The agent learns it needs engine_variant rather than guessing a filter, which is the recovery a person would perform by reading the page.
Chapter 3b · In plain language: a person and an agent buy the same shoe
Same store, two very different shoppers
The contract sounds abstract until you watch one purchase from both sides. Take the reorder: "the navy trail shoe in UK 8, wide." A person and an agent want the identical outcome. What they consume is not.
| Step | What a person does | What an agent needs |
|---|---|---|
| Find it | Types "trail runner 4 navy", scans the results, recognises the right family. | Sends TR4-NV-08-W and expects match_state:
exact, not a list to scan. |
| Confirm variant | Sees the navy image, clicks size 8 wide, trusts the swatch. | Reads results[].matched_options and variant_id, not an image it cannot interpret. |
| Check price | Reads "£159" on the card, in the right currency. | Reads results[].price.amount and currency as typed numbers, not a formatted string. |
| Handoff | Clicks the product, lands on the navy / 8 / wide page. | Follows handoff ?variant=8731 and expects
the page to open on that variant. |
The contract is just the page, written so software can act on it. Every field an agent consumes, a person inferred from layout, colour, and position. The contract removes the inference.
Chapter 5 · Diagnostic: which failure breaks which field
The contract is only as honest as the catalogue behind it
A structured answer over weak data is a faster wrong answer. Each row below names a catalogue failure and the exact contract field it corrupts, so you can trace an agent error back to its source.
| Catalogue failure | Breaks | Evidence |
|---|---|---|
| SKU stored but absent from searchable fields | query integrity and exact match | Barcode present in Shopify, not returned by the active search surface. |
| Matched variant not projected to the result | results[] variant identity | Family matches; card defaults to a different colour than the query named. |
| Attribute values as prose, not fields | facets and partial match | Colour exists only inside the description, so refinement cannot expose it. |
| Stale price or availability | results[] price and availability | Indexed state disagrees with the source of truth for the active market. |
| No normalisation across size systems | query constraint and continuation | Large, L, and lg resolve to three different filters for one product. |
The data side of each failure is covered in the agent-readable catalogue guide.
Chapter 6 · Test the contract
Treat the contract as a testable promise
The contract is only real if you can verify it. Run one query per agent job and confirm the response carries the field, not merely that a page rendered a product.
Pick one query per agent job: exact identifier, attribute, compatibility, comparison, content.
State the expected match_state, variant id, and count before inspecting the response.
Confirm the response carries the field, not merely that a page rendered the product.
Change one input at a time so a passing result explains what the system understood.
Record query, expected contract, actual contract, and date so future changes compare against evidence.
Research basis
Built on the human contract, not invented
This specification extends existing search intent and variant-search writing. The agent-specific additions are the match-state enum, the authorisation field, and the diagnostic mapping. Platform capability claims about native storefront search use Shopify's developer documentation.
Sources checked August 4, 2026
- Ecommerce Search Intent guide: The human response contract and query jobs this specification extends.
- Ecommerce Variant Search guide: The identifier-to-variant handoff trace the fixtures follow.
- Shopify Storefront API search: Reference for native storefront search. A typical search result is built for a human reader; confirm the exact fields your store returns before relying on any gap.
Where ParticleSearch fits
The contract is what good search already produces
Query understanding, variant precision, structured results, and honest match states are the day-to-day work of a search platform. The Agent Search Contract makes that work consumable by machines. ParticleSearch does not issue wallets or settle payments; it prepares the answer layer a funded agent needs.
Framework reflects the search intent and variant-search material current on August 4, 2026. Wallet and x402 capabilities remain subject to their vendors' release.
Review the ParticleSearch storefront experience