Aller au contenu principal
Version: Actuelle

Product · avancé — un service juridique

Le cas. Ouvrir une société, puis, en option, souscrire sa comptabilité. Ou souscrire la comptabilité seule, pour une société qui existe déjà.

Ce que l'exemple montre. Un item qui est une demande remplie, pas un produit : la garde (formulaire → éligibilité → devis) est le service. Deux parcours partagent une skill. La comptabilité lit le résultat de l'ouverture de la société dans le même submit.

examples/actuelle/product-advanced.yaml
# Product · advanced — a legal service: open a company, then (optionally) its accounting.
# The item is a FILLED REQUEST, not a product: the select guard (form → eligibility → quote) is the
# product. Two journeys share one skill; the accounting reads the company the formation opened.
station:
id: statuts-express
name: Statuts Express

global:
language: fr
currency: EUR
locale: fr-FR

domain:
domain_type: legaltech
entity_name: service
entity_name_plural: services

agent:
tone: professional
name: Statuts Express
persona: "un assistant juridique précis qui accompagne les fondateurs"
rules:
- "Ne jamais donner de conseil juridique contraignant : présenter les options, laisser les outils valider et tarifer."
- "Citer le nom et le prix exacts renvoyés par les outils, en euros."
portals:
web:
widget:
origins: [https://statuts-express.example.fr]

apis:
- name: juridique
openapi_url: https://api.statuts-express.example.fr/openapi.json
base_url: https://api.statuts-express.example.fr
operations:
- {id: recommendLegalStructure, access: read}
- {id: checkFormationEligibility, access: read}
- {id: quoteFormation, access: read}
- {id: openFormationDossier, access: write, reversible: false}
- {id: getAccountingPlans, access: read}
- {id: checkAccountingEligibility, access: read}
- {id: quoteAccounting, access: read}
- {id: subscribeAccounting, access: write, reversible: cancelSubscription}
- {id: cancelSubscription, access: write}
auth: {type: api_key, key_name: Authorization, key_location: header, key_env: STATUTS_KEY}

skills:
- name: formation
auto_trigger: open-company
cognitive:
objective: "recommander la structure juridique adaptée au projet"
diagnose: [l'activité, le nombre d'associés, le capital]
invoke: {method: recommendLegalStructure}
kinds: {company_formation: {}}
present:
fields:
name: {from: label, type: text, role: title}
price: {from: base_fee, type: price, role: billed}
select:
max_items: 1 # one company is being formed
guards:
- form:
activity: {type: text, required: true, label: "Activité de la société"}
capital: {type: number, required: true, label: "Capital social (€)"}
associates: {type: integer, required: true, label: "Nombre d'associés"}
hq_address: {type: text, required: true, label: "Adresse du siège"}
- check: checkFormationEligibility # the tenant says whether this structure fits
- update: {price: quoteFormation} # …and what it costs for THIS request
submit:
- name: open
mode: request
tool: openFormationDossier
args:
body.structure: "$item.fields.code"
body.activity: "$item.fields.activity"
body.capital: "$item.fields.capital"
body.associates: "$item.fields.associates"
body.hq_address: "$item.fields.hq_address"
body.fee: "$item.price"
body.idempotency_key: "$action.key"
output: {company_id: "$output.company_id"}

render: {component: cards}
- name: accounting
cognitive:
objective: "recommander le plan de comptabilité adapté au chiffre d'affaires"
diagnose: [le chiffre d'affaires estimé, la structure choisie]
invoke: {method: getAccountingPlans}
kinds: {accounting_subscription: {}}
present:
fields:
name: {from: label, type: text, role: title}
price: {from: price, type: price, role: billed}
select:
max_items: 1
guards:
- form:
est_revenue: {type: number, required: true, label: "Chiffre d'affaires estimé (€)"}
siren: {type: text, required: false, label: "SIREN (société existante)"}
- check: checkAccountingEligibility
- update: {price: quoteAccounting}
submit:
- name: subscribe
mode: request
tool: subscribeAccounting
args:
body.plan: "$item.fields.code"
body.est_revenue: "$item.fields.est_revenue"
body.siren: "$item.fields.siren"
# Value at submit (ADR-028 §3): filed AFTER the formation, in the same submit, and held
# if the formation failed. Alone, it resolves empty and the SIREN is used.
body.company_id: "$submitted[formation.open].company_id"
body.fee: "$item.price"
body.fee_cadence: "$item.price_cadence"
render: {component: cards}

playbooks:
- name: open-company
goal: "ouvrir une société : la structure, puis (option) la comptabilité"
tasks:
formation: {skill: formation, required: true, label: "Votre société"}
accounting: {skill: accounting, required: false, label: "Votre comptabilité", after: [formation]}
- name: subscribe-accounting
goal: "souscrire la comptabilité d'une société existante (SIREN)"
tasks:
accounting: {skill: accounting, required: true, label: "Votre comptabilité"}

submit_guard:
form:
accept_terms: {type: boolean, required: true, label: "J'accepte les conditions générales"}
confirm: true

Ce qui se passe​

étapeCorerésultat
« je crée une SAS avec un associé »formation → recommendLegalStructure; auto_trigger ouvre open-companycartes des structures
un plan comptable demandé d'abordstep_open : la tâche accounting a after: [formation]refusé, avec la raison : la société d'abord
SAS choisieformulaire (activité, capital, associés, siège), puis checkFormationEligibility, puis quoteFormationla ligne entre avec son prix
un plan comptable choisiformulaire, éligibilité, devisdeuxième ligne, prix mensuel
« Finaliser »accept_terms + confirmopenFormationDossier, puis subscribeAccounting avec company_id
l'ouverture échoueADR-028 §3la comptabilité est mise en attente, jamais déposée sur une société absente
« j'ai déjà une SARL, SIREN 812… »l'agent appelle start_playbook : subscribe-accountingcompany_id vide, le SIREN est utilisé

À retenir​

  • $submitted[formation.open].company_id est une dépendance à l'exécution : même submit, dans l'ordre, et rien n'est déposé si le parent a échoué.
  • Le prix vient du tenant, pour cette demande : update: {price: quoteFormation}, transmis par body.fee.
  • openFormationDossier est déclarée reversible: false : la porte MCP annonce le submit comme destructif. subscribeAccounting nomme l'opération qui l'annule (cancelSubscription) ; rien ne l'appelle encore.
  • Dans open-company, after: [formation] impose l'ordre au choix : la comptabilité ne s'ouvre qu'une fois la société choisie. La version cible fait de l'ouverture un sous-playbook.