Product · simple — a shop
The case. The same shop as in the current version. Nothing new on the journey side: it is the shape of the config that changes.
What changes. The search parameter says who can set it. A profile receives the search
operation. The station starts in observe: no model acts.
examples/cible/product-simple.yaml
# Product · simple — CIBLE. The same shop as the actuelle example, in the target shape:
# fields are typed, operations say read or write.
station:
id: maison-indigo
kind: product
name: Maison Indigo
guidance: {max_mode: observe} # no model acts until the station is calibrated
global: # applies to every field of its type, every skill
language: fr
currency: EUR # every `type: price` field
locale: fr-FR
timezone: Europe/Paris
apis:
- name: boutique
openapi_url: https://api.maison-indigo.example.fr/openapi.json
base_url: https://api.maison-indigo.example.fr
auth: {type: none}
operations:
- {id: searchProducts, access: read}
profiles: # everything is closed until a profile is granted an operation
anonyme: {when: "identity.authenticated == false", grants: [boutique.searchProducts]}
skills:
- name: articles
cognitive:
objective: "aider à trouver le tissu ou le vêtement qui correspond au projet"
diagnose: [l'usage, la couleur, le budget]
params:
q: {type: text, set_by: [llm, person]} # what the person is looking for
invoke:
method: searchProducts
args: {q: "$params.q"}
present:
fields:
name: {from: name, type: text, role: title}
price: {from: price, type: price, role: billed}
image: {from: image_url, type: image}
page: {from: slug, type: url, role: link, # the shop's own page for this article
template: "https://maison-indigo.example.fr/article/{value}"}
submit:
- {name: commande, mode: handover, url: "https://maison-indigo.example.fr/commande?add={items}"}
render: {component: carousel}
submit_guard:
confirm: true
agent: # the agent Convoy deploys: a client of this station, like any other
name: Maison Indigo
persona: "une conseillère textile qui connaît chaque tissu de l'atelier"
tone: friendly
rules:
- "Ne jamais inventer un article ou un prix : tout vient de l'outil."
emoji: false # a discreet emoji in replies, or none
model: gemini-2.5-flash # the model the agent runs on
portals:
web:
widget:
origins: [https://maison-indigo.example.fr] # the only sites the widget may load on
theme: {primary: "#24508f", secondary: "#f2ede4", font: manrope} # the widget's colours and typeface
What happens
| the person or the agent | Core | result |
|---|---|---|
| "a blue wax print for a dress" | articles: read of searchProducts | a carousel; a read trace in the room |
| adds two items | no guard | two reserved actions, total in euros |
| "Finalise" | confirm; no one but the person in the room (default) | the link to the tenant's site |
Key points
- A simple station stays simple: one profile, no policy, no playbook. The
anonymeprofile receivesboutique.searchProducts, because everything is closed by default. role: billedsays which field is the billed price; an item can carry anotherpricefield (a struck-through price) without ambiguity.