Skip to content

browse_catalog: skill contract

browse_catalog returns catalog products for an optional free-text query and category filter. Every request field is optional; a call with an empty arguments object should return the first page of your catalog. If nothing matches, return { "products": [], "next_cursor": null }.

Machine-readable: /skills/v1/browse_catalog.request.schema.json

FieldTypeRequiredNotes
querystringnoFree-text search over title / description. 1–256 chars.
categorystringnoCategory / collection filter. 1–128 chars.
limitintegernoPage size, 1–50. When absent, choose your own default; 10 is typical.
cursorstringnoOpaque page cursor returned in a prior next_cursor. 1–512 chars.
{
"additionalProperties": false,
"properties": {
"category": {
"maxLength": 128,
"minLength": 1,
"type": "string"
},
"cursor": {
"maxLength": 512,
"minLength": 1,
"type": "string"
},
"limit": {
"maximum": 50,
"minimum": 1,
"type": "integer"
},
"query": {
"maxLength": 256,
"minLength": 1,
"type": "string"
}
},
"type": "object"
}
{
"skill_id": "browse_catalog",
"site_id": "01EXAMPLE00000000000000000",
"arguments": {
"query": "medium roast",
"limit": 10
},
"observed_at": "2026-07-05T18:22:15.140Z",
"nonce": "01K1EXAMPLE0000000000000000"
}

Machine-readable: /skills/v1/browse_catalog.response.schema.json

Return a JSON body with:

FieldTypeRequiredNotes
productsarrayyesUp to 128 products matching the query. Return no more than limit when it is set.
next_cursorstring | nullyesYour cursor for the next page, or null on the last page. Up to 512 chars. The agent sends it back as cursor to get the next page.

Each product has:

FieldTypeRequiredNotes
skustringyesYour SKU. 1–256 chars.
titlestringyesProduct title. 1–512 chars.
priceobjectyes{ amount, amount_decimal, currency }.
availabilityenumyesin_stock | low_stock | out_of_stock | unknown.
descriptionstringno1–2048 chars.
urlstringno1–2048 chars.
image_urlstringno1–2048 chars.
brandstringno1–256 chars.
variantsarraynoPresent on multi-variant products only; up to 64.
optionsarraynoPresent on multi-variant products only; up to 32.
has_more_variantsbooleannotrue when the product has more variants than were returned.

price (and a variant’s price) has three fields:

FieldTypeNotes
amountnumberThe price in minor units (cents, pence), as an integer. 1800 is $18.00.
amount_decimalstringThe same price as a decimal string, for example "18.00". 1–64 chars.
currencystringISO 4217 code in uppercase, for example USD. 3–8 chars.

Keep amount and amount_decimal consistent. Sill does not compare them, and agents may show either one to a shopper.

For a product with variants (for example sizes or grinds):

FieldShape
optionsUp to 32 of { name, values[] }, for example { "name": "Grind", "values": ["Whole bean", "Espresso"] }. Up to 64 values each.
variantsUp to 64 of { sku, title, price, availability, options? }, where each variant’s options is a list of { name, value }.
has_more_variantsSet to true when you returned fewer variants than the product has.
{
"additionalProperties": false,
"properties": {
"next_cursor": {
"maxLength": 512,
"type": ["string", "null"]
},
"products": {
"items": {
"additionalProperties": false,
"properties": {
"availability": {
"enum": ["in_stock", "low_stock", "out_of_stock", "unknown"],
"type": "string"
},
"brand": { "maxLength": 256, "minLength": 1, "type": "string" },
"description": { "maxLength": 2048, "minLength": 1, "type": "string" },
"has_more_variants": { "type": "boolean" },
"image_url": { "maxLength": 2048, "minLength": 1, "type": "string" },
"options": {
"items": {
"additionalProperties": false,
"properties": {
"name": { "maxLength": 128, "minLength": 1, "type": "string" },
"values": {
"items": { "maxLength": 256, "minLength": 1, "type": "string" },
"maxItems": 64,
"type": "array"
}
},
"required": ["name", "values"],
"type": "object"
},
"maxItems": 32,
"type": "array"
},
"price": {
"additionalProperties": false,
"properties": {
"amount": { "type": "number" },
"amount_decimal": { "maxLength": 64, "minLength": 1, "type": "string" },
"currency": { "maxLength": 8, "minLength": 3, "type": "string" }
},
"required": ["amount", "amount_decimal", "currency"],
"type": "object"
},
"sku": { "maxLength": 256, "minLength": 1, "type": "string" },
"title": { "maxLength": 512, "minLength": 1, "type": "string" },
"url": { "maxLength": 2048, "minLength": 1, "type": "string" },
"variants": {
"items": {
"additionalProperties": false,
"properties": {
"availability": {
"enum": ["in_stock", "low_stock", "out_of_stock", "unknown"],
"type": "string"
},
"options": {
"items": {
"additionalProperties": false,
"properties": {
"name": { "maxLength": 128, "minLength": 1, "type": "string" },
"value": { "maxLength": 256, "minLength": 1, "type": "string" }
},
"required": ["name", "value"],
"type": "object"
},
"maxItems": 32,
"type": "array"
},
"price": {
"additionalProperties": false,
"properties": {
"amount": { "type": "number" },
"amount_decimal": { "maxLength": 64, "minLength": 1, "type": "string" },
"currency": { "maxLength": 8, "minLength": 3, "type": "string" }
},
"required": ["amount", "amount_decimal", "currency"],
"type": "object"
},
"sku": { "maxLength": 256, "minLength": 1, "type": "string" },
"title": { "maxLength": 512, "minLength": 1, "type": "string" }
},
"required": ["sku", "title", "price", "availability"],
"type": "object"
},
"maxItems": 64,
"type": "array"
}
},
"required": ["sku", "title", "price", "availability"],
"type": "object"
},
"maxItems": 128,
"type": "array"
}
},
"required": ["products", "next_cursor"],
"type": "object"
}
{
"products": [
{
"sku": "beans_medium_12oz",
"title": "Medium roast, 12 oz bag",
"description": "Ethiopian, natural process.",
"price": {
"amount": 1800,
"amount_decimal": "18.00",
"currency": "USD"
},
"availability": "in_stock",
"url": "https://example.com/products/beans-medium-12oz"
}
],
"next_cursor": "opaque-page-2-token"
}

Sill checks your response against the response schema before an agent sees it. A response that fails is not passed on and counts as a failed call; 3 failures in a row mark the skill UNREACHABLE. Common causes:

  • An extra field at any depth, such as internal_notes on a product.
  • An availability value outside in_stock, low_stock, out_of_stock, unknown.
  • A missing next_cursor. Send null on the last page; do not leave the field out.

Check the X-Sill-Signature header on every request before answering. The scheme is the same for every skill; see Verify the signature for tested TypeScript, Python and Go code.