Comprendre le tour précédent et proposer les questions suivantes
Route principale du runtime. En un seul appel, le moteur résout la question
réellement posée et son outcome, applique les mises à jour du client, réduit
l’état, recalcule les progressions, puis classe les questions éligibles.
Le client n’a pas à savoir quelle candidate son agent a utilisée : si
decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis
la décision en attente, le texte de l’agent, la réponse structurée et le
contexte. Une reformulation de la question par l’agent hôte reste
rattachable.
Au premier appel d’une session neuve, previous_turn est absent.
Lorsque previous_turn répond à la dernière question autorisée par
max_turns, ce tour est enregistré puis la réponse est action: stop avec
stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt.
/events peut remplacer la décision en attente après que l’agent hôte a déjà
posé sa question. Une réponse dont previous_turn.decision_id désigne la
dernière décision remplacée est donc acceptée jusqu’au prochain /next
abouti :
si previous_turn.question_id figure encore parmi les candidates de la
décision courante, la réponse lui est rattachée normalement ;
sinon, previous_turn est lu comme un contexte en mode messages : les
données qu’il contient sont extraites, aucun outcome n’est enregistré pour
la question retirée et aucun tour n’est consommé. La réponse renvoie la
décision courante, avec le même decision_id, si la sélection la redonne à
l’identique, et sinon une nouvelle décision.
Un decision_id qui ne désigne ni la décision en attente ni la dernière
décision remplacée reste refusé en invalid_previous_turn.
Envoyez la clé API dans Authorization: Bearer <clé>. Elle identifie le domaine et les droits autorisés. Ne transmettez pas d'en-têtes d'identité internes.
En-têtes
Idempotency-Key
string
requis
Clé unique par mutation logique, choisie par l'appelant.
Même clé et même corps renvoient exactement la réponse d'origine, sans
rejouer l'effet : aucun retry ne double turn_count, un outcome, un
événement, un feedback ou une publication. Même clé avec un corps différent
produit 409 idempotency_key_reused.
Les enregistrements sont isolés par tenant et par opération, et sont purgés
après 24 heures. Passé ce délai, la même clé est traitée comme neuve.
Required string length: 8 - 128
Paramètres de chemin
session_id
string
requis
Identifiant opaque de session attribué par Zelinqa à la création.
Required string length: 1 - 128
Corps
application/json
state_version
integer
requis
Version lue par le client avant cette mutation, en contrôle optimiste.
Plage requise: x >= 0
previous_turn
object
Observation du dernier échange ; absente au premier appel d'une session neuve. Les identifiants de décision et de question sont facultatifs et ne doivent pas être inventés. Pour une question ouverte répondue, user_text non vide est obligatoire, sauf si outcome vaut explicitement asked_no_answer ou refused. Sinon, l'API renvoie 422 invalid_previous_turn avant toute analyse par modèle. Les questions fermées et semi-ouvertes acceptent des choice_ids seuls ; une semi-ouverte peut aussi porter free_text. Ni context_update ni client_updates ne remplacent le texte requis.
Show child attributes
context_update
object
Contexte apparu depuis le dernier appel Zelinqa. Le client choisit un résumé
compact ou le delta ordonné des messages ; il ne renvoie jamais l'historique
déjà traité.
Option 1
Option 2
Show child attributes
client_updates
object
Mises à jour explicites du système appelant, prioritaires sur l'inférence.
Show child attributes
selection
object
Contraintes valables pour cet appel uniquement. Elles sont appliquées avant
le calcul du classement, jamais en filtrant un top 3 déjà constitué.
Show child attributes
Réponse
Décision calculée, ou arrêt explicite lorsque la limite de tours est atteinte
ou qu'aucune question n'existe.
Aucun score de sélection n'est exposé : le classement est porté par rank.
Un score brut n'a pas de sens métier hors du moteur et ne doit pas devenir
une dépendance des intégrations.
Invariants garantis par le moteur, non exprimés en JSON Schema pour
rester générables en SDK :
action: ask implique decision_id non nul, stop_reason nul et au
moins un candidat ;
action: stop implique decision_id nul, stop_reason renseigné et
candidates vide.
request_id
string
requis
session_id
string
requis
decision_id
string | null
requis
Non nul quand action vaut ask. À renvoyer dans le tour suivant si disponible.
action
enum<string>
requis
stop est produit dans deux cas, précisés par stop_reason : la limite
max_turns est atteinte, ou aucune question identifiable n'existe. Un
objectif déjà atteint ou une éligibilité normale vide ne coupent pas la
conversation : le moteur propose encore la meilleure question disponible
et le signale dans warnings. Avant la limite de tours, la décision
d'arrêter appartient à l'appelant.
Options disponibles:
ask,
stop
stop_reason
enum<string> | null
requis
Cause de l'arrêt :
max_turns_reached : la session a atteint max_turns. Le dernier tour
autorisé est enregistré ; les appels /next suivants renvoient le même
arrêt sans analyser le tour ni modifier la session ;
no_question_available : aucune question identifiable ne subsiste après
application des exclusions dures — question inactive, dimension exclu par
le client, contrainte stricte de l'appel.
Les autres situations terminales remontent par warnings, la conversation
restant décidée par l'appelant.
Options disponibles:
no_question_available,
max_turns_reached
candidates
object[]
requis
Ordonnées par pertinence décroissante, rang 1 en premier. Lorsque
plusieurs candidats sont demandés, le moteur simule la couverture
apportée par le premier avant de choisir le suivant : deux variantes
demandant la même information ne sont pas retournées ensemble.
Maximum array length: 10
Show child attributes
progress
object
requis
Show child attributes
turn_count
integer
requis
Plage requise: x >= 0
turns_remaining
integer
requis
Vaut 0 lorsque la limite de tours est atteinte ; action vaut alors stop.
Plage requise: x >= 0
warnings
enum<string>[]
requis
Conditions d'arrêt réunies, sans que Zelinqa interrompe la conversation.
objective_achieved : les conditions de réussite sont satisfaites ;
eligibility_exhausted_fallback : plus aucune question n'était éligible
normalement, la proposition est un repli — elle porte tout de même un
question_id valide et respecte les exclusions dures ;
constraints_relaxed : une préférence prefer a dû être élargie.
Options disponibles:
objective_achieved,
eligibility_exhausted_fallback,
constraints_relaxed
degraded
boolean
requis
Vrai lorsque la compréhension du tour a été effectuée en mode réduit.
degraded_reasons
enum<string>[]
requis
Options disponibles:
missing_user_text,
summary_only_context,
semantic_service_unavailable,
unresolved_previous_turn
versions
object
requis
La version de configuration épinglée par la session n'est pas exposée : le
client ne la choisit pas et ne doit pas s'y adosser.
Show child attributes
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Zelinqa","colors":{"primary":"#7C3AED","light":"#A78BFA","dark":"#8B5CF6"},"logo":{"light":"https://mintcdn.com/zelinqa-d77427f3/NHQX6jXz7QClMoqF/logo/light.svg?fit=max\u0026auto=format\u0026n=NHQX6jXz7QClMoqF\u0026q=85\u0026s=6cbe3336a207008182be0916b85b70ef","dark":"https://mintcdn.com/zelinqa-d77427f3/NHQX6jXz7QClMoqF/logo/dark.svg?fit=max\u0026auto=format\u0026n=NHQX6jXz7QClMoqF\u0026q=85\u0026s=7ff1e5b30a949dd04c9ea9b6f3e6beaa","href":"https://zelinqa.ai"},"favicon":"https://mintcdn.com/zelinqa-d77427f3/04zoXbeL2ZlFQrrw/favicon.svg?fit=max\u0026auto=format\u0026n=04zoXbeL2ZlFQrrw\u0026q=85\u0026s=76e8077a8df9fee9dce67ea7cf0612cb","api":{"openapi":["openapi.fr.yaml","openapi.yaml"],"playground":{"display":"interactive"},"examples":{"languages":["bash","python","javascript"]}},"navbar":{"primary":{"type":"button","label":"Zelinqa Studio","href":"https://client.zelinqa.ai"}},"styling":{"latex":false},"navigation":{"languages":[{"language":"fr","default":true,"href":"fr/introduction"},{"language":"en","href":"en/introduction"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"zelinqa-d77427f3","hasAudioNarration":false,"actualSubdomain":"zelinqa-d77427f3","customDomains":["docs.zelinqa.ai"],"gitSource":{"type":"github","owner":"zelinqa","repo":"nbq-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ad54348ae0c8a39b0082ad1","clientVersion":"0.0.4142","searchFilterCounts":[{"language":"en","tag":"API Reference","count":17},{"language":"fr","tag":"Référence API","count":17},{"language":"en","tag":"Developers","count":14},{"language":"fr","tag":"Développeurs","count":14},{"language":"en","tag":"Zelinqa Studio","count":11},{"language":"fr","tag":"Zelinqa Studio","count":11},{"language":"en","tag":"Configure","count":6},{"language":"en","tag":"Configuration","count":6},{"language":"fr","tag":"Configurer","count":6},{"language":"fr","tag":"Configuration","count":6},{"language":"en","tag":"API guides","count":5},{"language":"en","tag":"Guides","count":5},{"language":"en","tag":"Publish and operate","count":5},{"language":"en","tag":"Sessions","count":5},{"language":"fr","tag":"Guides API","count":5},{"language":"fr","tag":"Guides","count":5},{"language":"fr","tag":"Publier et exploiter","count":5},{"language":"fr","tag":"Sessions","count":5},{"language":"en","tag":"Resources","count":3},{"language":"fr","tag":"Ressources","count":3}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"custom.css","content":""}],"page":{"pagePath":"api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes","slug":"/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes","pageMetadata":{"title":"Comprendre le tour précédent et proposer les questions suivantes","description":"Route principale du runtime. En un seul appel, le moteur résout la question\nréellement posée et son outcome, applique les mises à jour du client, réduit\nl'état, recalcule les progressions, puis classe les questions éligibles.\n\nLe client n'a pas à savoir quelle candidate son agent a utilisée : si\n`decision_id`, `question_id` ou `outcome` sont absents, Zelinqa les résout depuis\nla décision en attente, le texte de l'agent, la réponse structurée et le\ncontexte. Une reformulation de la question par l'agent hôte reste\nrattachable.\n\nAu premier appel d'une session neuve, `previous_turn` est absent.\n\nLorsque `previous_turn` répond à la dernière question autorisée par\n`max_turns`, ce tour est enregistré puis la réponse est `action: stop` avec\n`stop_reason: max_turns_reached`. Les appels suivants renvoient le même arrêt.\n\n`/events` peut remplacer la décision en attente après que l'agent hôte a déjà\nposé sa question. Une réponse dont `previous_turn.decision_id` désigne la\ndernière décision remplacée est donc acceptée jusqu'au prochain `/next`\nabouti :\n- si `previous_turn.question_id` figure encore parmi les candidates de la\n décision courante, la réponse lui est rattachée normalement ;\n- sinon, `previous_turn` est lu comme un contexte en mode messages : les\n données qu'il contient sont extraites, aucun outcome n'est enregistré pour\n la question retirée et aucun tour n'est consommé. La réponse renvoie la\n décision courante, avec le même `decision_id`, si la sélection la redonne à\n l'identique, et sinon une nouvelle décision.\n\nUn `decision_id` qui ne désigne ni la décision en attente ni la dernière\ndécision remplacée reste refusé en `invalid_previous_turn`.\n","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions/{session_id}/next","href":"/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n p: \"p\",\n ul: \"ul\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.p, {\n children: \"Route principale du runtime. En un seul appel, le moteur résout la question\\nréellement posée et son outcome, applique les mises à jour du client, réduit\\nl’état, recalcule les progressions, puis classe les questions éligibles.\"\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Le client n’a pas à savoir quelle candidate son agent a utilisée : si\\n\", _jsx(_components.code, {\n children: \"decision_id\"\n }), \", \", _jsx(_components.code, {\n children: \"question_id\"\n }), \" ou \", _jsx(_components.code, {\n children: \"outcome\"\n }), \" sont absents, Zelinqa les résout depuis\\nla décision en attente, le texte de l’agent, la réponse structurée et le\\ncontexte. Une reformulation de la question par l’agent hôte reste\\nrattachable.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Au premier appel d’une session neuve, \", _jsx(_components.code, {\n children: \"previous_turn\"\n }), \" est absent.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Lorsque \", _jsx(_components.code, {\n children: \"previous_turn\"\n }), \" répond à la dernière question autorisée par\\n\", _jsx(_components.code, {\n children: \"max_turns\"\n }), \", ce tour est enregistré puis la réponse est \", _jsx(_components.code, {\n children: \"action: stop\"\n }), \" avec\\n\", _jsx(_components.code, {\n children: \"stop_reason: max_turns_reached\"\n }), \". Les appels suivants renvoient le même arrêt.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.code, {\n children: \"/events\"\n }), \" peut remplacer la décision en attente après que l’agent hôte a déjà\\nposé sa question. Une réponse dont \", _jsx(_components.code, {\n children: \"previous_turn.decision_id\"\n }), \" désigne la\\ndernière décision remplacée est donc acceptée jusqu’au prochain \", _jsx(_components.code, {\n children: \"/next\"\n }), \"\\nabouti :\"]\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [\"si \", _jsx(_components.code, {\n children: \"previous_turn.question_id\"\n }), \" figure encore parmi les candidates de la\\ndécision courante, la réponse lui est rattachée normalement ;\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"sinon, \", _jsx(_components.code, {\n children: \"previous_turn\"\n }), \" est lu comme un contexte en mode messages : les\\ndonnées qu’il contient sont extraites, aucun outcome n’est enregistré pour\\nla question retirée et aucun tour n’est consommé. La réponse renvoie la\\ndécision courante, avec le même \", _jsx(_components.code, {\n children: \"decision_id\"\n }), \", si la sélection la redonne à\\nl’identique, et sinon une nouvelle décision.\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Un \", _jsx(_components.code, {\n children: \"decision_id\"\n }), \" qui ne désigne ni la décision en attente ni la dernière\\ndécision remplacée reste refusé en \", _jsx(_components.code, {\n children: \"invalid_previous_turn\"\n }), \".\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Comprendre le tour précédent et proposer les questions suivantes","description":"Route principale du runtime. En un seul appel, le moteur résout la question\nréellement posée et son outcome, applique les mises à jour du client, réduit\nl'état, recalcule les progressions, puis classe les questions éligibles.\n\nLe client n'a pas à savoir quelle candidate son agent a utilisée : si\n`decision_id`, `question_id` ou `outcome` sont absents, Zelinqa les résout depuis\nla décision en attente, le texte de l'agent, la réponse structurée et le\ncontexte. Une reformulation de la question par l'agent hôte reste\nrattachable.\n\nAu premier appel d'une session neuve, `previous_turn` est absent.\n\nLorsque `previous_turn` répond à la dernière question autorisée par\n`max_turns`, ce tour est enregistré puis la réponse est `action: stop` avec\n`stop_reason: max_turns_reached`. Les appels suivants renvoient le même arrêt.\n\n`/events` peut remplacer la décision en attente après que l'agent hôte a déjà\nposé sa question. Une réponse dont `previous_turn.decision_id` désigne la\ndernière décision remplacée est donc acceptée jusqu'au prochain `/next`\nabouti :\n- si `previous_turn.question_id` figure encore parmi les candidates de la\n décision courante, la réponse lui est rattachée normalement ;\n- sinon, `previous_turn` est lu comme un contexte en mode messages : les\n données qu'il contient sont extraites, aucun outcome n'est enregistré pour\n la question retirée et aucun tour n'est consommé. La réponse renvoie la\n décision courante, avec le même `decision_id`, si la sélection la redonne à\n l'identique, et sinon une nouvelle décision.\n\nUn `decision_id` qui ne désigne ni la décision en attente ni la dernière\ndécision remplacée reste refusé en `invalid_previous_turn`.\n","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions/{session_id}/next","href":"/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["sessions"],"summary":"Comprendre le tour précédent et proposer les questions suivantes","description":"Route principale du runtime. En un seul appel, le moteur résout la question\nréellement posée et son outcome, applique les mises à jour du client, réduit\nl'état, recalcule les progressions, puis classe les questions éligibles.\n\nLe client n'a pas à savoir quelle candidate son agent a utilisée : si\n`decision_id`, `question_id` ou `outcome` sont absents, Zelinqa les résout depuis\nla décision en attente, le texte de l'agent, la réponse structurée et le\ncontexte. Une reformulation de la question par l'agent hôte reste\nrattachable.\n\nAu premier appel d'une session neuve, `previous_turn` est absent.\n\nLorsque `previous_turn` répond à la dernière question autorisée par\n`max_turns`, ce tour est enregistré puis la réponse est `action: stop` avec\n`stop_reason: max_turns_reached`. Les appels suivants renvoient le même arrêt.\n\n`/events` peut remplacer la décision en attente après que l'agent hôte a déjà\nposé sa question. Une réponse dont `previous_turn.decision_id` désigne la\ndernière décision remplacée est donc acceptée jusqu'au prochain `/next`\nabouti :\n- si `previous_turn.question_id` figure encore parmi les candidates de la\n décision courante, la réponse lui est rattachée normalement ;\n- sinon, `previous_turn` est lu comme un contexte en mode messages : les\n données qu'il contient sont extraites, aucun outcome n'est enregistré pour\n la question retirée et aucun tour n'est consommé. La réponse renvoie la\n décision courante, avec le même `decision_id`, si la sélection la redonne à\n l'identique, et sinon une nouvelle décision.\n\nUn `decision_id` qui ne désigne ni la décision en attente ni la dernière\ndécision remplacée reste refusé en `invalid_previous_turn`.\n","operationId":"nextQuestions","x-required-scopes":["runtime"],"parameters":["b1754f65-23be-4dae-82a0-62d1be17b4c3","cf02d0da-c1df-41f6-910a-4b1b1c0e2a7d"],"requestBody":"c6d83caa-1774-44aa-9070-6a047ab54ada","responses":{"200":"bd52f896-1725-4174-b2e2-c57490985bc7","401":"10515b5b-98e1-4a18-8125-95c38a75fc93","403":"b335d75a-5676-4fc4-bccf-1dd816757d15","404":"9c610e69-6c40-4aa1-9f5e-6ca48fe94c96","409":"20c78f34-4862-4533-a674-9f516b85197f","410":"d8f18170-f16a-4543-931a-b9b8b1f539e8","422":"f3065aa6-e157-46a2-af6d-77c3656d45b7","503":"99ef41a4-e22a-4187-8a24-2aab609d3c70"},"method":"post","type":"path","servers":["1a6b3648-7307-43a6-aa3e-c2fc73c4533a"],"security":["9a21f59e-73e7-40cb-aed4-69ae805ab1b8"],"path":"/v1/sessions/{session_id}/next","baseUrlOptions":["https://api.zelinqa.ai"],"title":"Comprendre le tour précédent et proposer les questions suivantes","codeSamples":[],"requestExampleLanguages":["bash","python","javascript"],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"b1754f65-23be-4dae-82a0-62d1be17b4c3":{"name":"session_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"description":"Identifiant opaque de session attribué par Zelinqa à la création.","uniqueKey":"","typeLabel":"string"},"description":"Identifiant opaque de session attribué par Zelinqa à la création."},"cf02d0da-c1df-41f6-910a-4b1b1c0e2a7d":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128,"isRequired":true,"description":"Clé unique par mutation logique, choisie par l'appelant.\n\nMême clé et même corps renvoient exactement la réponse d'origine, sans\nrejouer l'effet : aucun retry ne double `turn_count`, un outcome, un\névénement, un feedback ou une publication. Même clé avec un corps différent\nproduit `409 idempotency_key_reused`.\n\nLes enregistrements sont isolés par tenant et par opération, et sont purgés\naprès **24 heures**. Passé ce délai, la même clé est traitée comme neuve.\n","uniqueKey":"","typeLabel":"string"},"description":"Clé unique par mutation logique, choisie par l'appelant.\n\nMême clé et même corps renvoient exactement la réponse d'origine, sans\nrejouer l'effet : aucun retry ne double `turn_count`, un outcome, un\névénement, un feedback ou une publication. Même clé avec un corps différent\nproduit `409 idempotency_key_reused`.\n\nLes enregistrements sont isolés par tenant et par opération, et sont purgés\naprès **24 heures**. Passé ce délai, la même clé est traitée comme neuve.\n"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["state_version"],"properties":{"state_version":{"type":"integer","minimum":0,"description":"Version lue par le client avant cette mutation, en contrôle optimiste.","isRequired":true,"uniqueKey":"state_version","typeLabel":"integer"},"previous_turn":{"type":"object","additionalProperties":false,"minProperties":1,"description":"Observation du dernier échange ; absente au premier appel d'une session neuve. Les identifiants de décision et de question sont facultatifs et ne doivent pas être inventés. Pour une question ouverte répondue, user_text non vide est obligatoire, sauf si outcome vaut explicitement asked_no_answer ou refused. Sinon, l'API renvoie 422 invalid_previous_turn avant toute analyse par modèle. Les questions fermées et semi-ouvertes acceptent des choice_ids seuls ; une semi-ouverte peut aussi porter free_text. Ni context_update ni client_updates ne remplacent le texte requis.","properties":{"decision_id":{"type":"string","minLength":1,"maxLength":128,"description":"Décision à laquelle ce tour répond. La dernière décision remplacée par\n`/events` reste acceptée jusqu'au prochain `/next` abouti : la réponse\nest rattachée à `question_id` s'il figure encore parmi les candidates\ncourantes, sinon lue comme contexte, sans outcome ni tour consommé.\n","uniqueKey":"previous_turn.decision_id","typeLabel":"string"},"question_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"previous_turn.question_id","typeLabel":"string"},"outcome":{"type":"string","enum":["asked_answered","asked_no_answer","refused"],"description":"Résultat d'une question effectivement posée.\n\n- `asked_answered` : question posée et réponse exploitable reçue ;\n- `asked_no_answer` : question posée, aucune réponse exploitable ;\n- `refused` : refus explicite de répondre.\n\nUne question jamais posée n'a pas de résultat : elle est simplement absente.\nIl n'existe pas de valeur `skipped` — une proposition que l'agent n'a pas\nutilisée est journalisée comme décision ignorée, jamais comme un faux\nrésultat sur la question.\n","uniqueKey":"previous_turn.outcome","typeLabel":"enum\u003cstring>"},"assistant_text":{"type":"string","minLength":1,"maxLength":8000,"description":"Question ou message réellement envoyé par l'agent hôte, éventuellement reformulé.","uniqueKey":"previous_turn.assistant_text","typeLabel":"string"},"user_text":{"type":"string","minLength":1,"maxLength":8000,"description":"Réponse réellement donnée par la personne. Obligatoire pour une question ouverte répondue, sauf outcome asked_no_answer ou refused ; facultative pour une question fermée ou semi-ouverte. Un texte fourni peut être analysé par le moteur.","uniqueKey":"previous_turn.user_text","typeLabel":"string"},"structured_answer":{"type":"object","additionalProperties":false,"required":["choice_ids"],"description":"Réponse à une question à choix. Le mapping choix vers information de réussite\nest déterministe et compilé à la publication : aucun appel LLM n'est effectué\npour l'interpréter.\n","properties":{"choice_ids":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"previous_turn.structured_answer.choice_ids.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"previous_turn.structured_answer.choice_ids","typeLabel":"string[]"},"free_text":{"type":"string","minLength":1,"maxLength":4000,"description":"Complément libre, autorisé uniquement pour une question `semi_open`.","uniqueKey":"previous_turn.structured_answer.free_text","typeLabel":"string"}},"uniqueKey":"previous_turn.structured_answer","typeLabel":"object"},"message_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"previous_turn.message_id","typeLabel":"string"}},"uniqueKey":"previous_turn","typeLabel":"object"},"context_update":{"oneOf":[{"type":"object","description":"Contexte apparu depuis le dernier appel Zelinqa. Le client choisit un résumé\ncompact ou le delta ordonné des messages ; il ne renvoie jamais l'historique\ndéjà traité.\n","required":["mode","text"],"properties":{"mode":{"type":"string","const":"summary","isRequired":true,"uniqueKey":"context_update.oneOf.0.mode","typeLabel":"string"},"text":{"type":"string","minLength":1,"maxLength":16000,"isRequired":true,"uniqueKey":"context_update.oneOf.0.text","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"context_update.oneOf.0","typeLabel":"object"},{"type":"object","description":"Contexte apparu depuis le dernier appel Zelinqa. Le client choisit un résumé\ncompact ou le delta ordonné des messages ; il ne renvoie jamais l'historique\ndéjà traité.\n","required":["mode","messages"],"properties":{"mode":{"type":"string","const":"messages","isRequired":true,"uniqueKey":"context_update.oneOf.1.mode","typeLabel":"string"},"messages":{"type":"array","minItems":1,"maxItems":100,"items":{"oneOf":[{"type":"object","description":"Message du delta de contexte. Une `structured_answer` portée par un\nmessage utilisateur est mappée déterministement, sans LLM, comme pour\n`previous_turn` — elle exige donc `question_id` : sans lui, la requête\nest rejetée en `invalid_previous_turn`. Un `question_id` connu du\ncorpus rend les cibles de cette question vérifiables par l'extraction,\nmême hors décision en attente.\n","required":["role","text"],"properties":{"role":{"type":"string","enum":["user","assistant"],"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.role","typeLabel":"enum\u003cstring>"},"text":{"type":"string","minLength":1,"maxLength":8000,"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.text","typeLabel":"string"},"message_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.message_id","typeLabel":"string"},"question_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.question_id","typeLabel":"string"},"structured_answer":{"type":"object","additionalProperties":false,"required":["choice_ids"],"description":"Réponse structurée rapportée dans le delta. Obligatoirement\naccompagnée de `question_id` (le schéma ne porte pas de if/then :\nla règle est appliquée par le runtime, code `invalid_previous_turn`).\n","properties":{"choice_ids":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.structured_answer.choice_ids.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.structured_answer.choice_ids","typeLabel":"string[]"},"free_text":{"type":"string","minLength":1,"maxLength":4000,"description":"Complément libre, autorisé uniquement pour une question `semi_open`.","uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.structured_answer.free_text","typeLabel":"string"}},"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.structured_answer","typeLabel":"object"},"occurred_at":{"type":"string","format":"date-time","uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0.occurred_at","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"Message du delta de contexte. Une `structured_answer` portée par un\nmessage utilisateur est mappée déterministement, sans LLM, comme pour\n`previous_turn` — elle exige donc `question_id` : sans lui, la requête\nest rejetée en `invalid_previous_turn`. Un `question_id` connu du\ncorpus rend les cibles de cette question vérifiables par l'extraction,\nmême hors décision en attente.\n","required":["role","structured_answer"],"properties":{"role":{"type":"string","enum":["user","assistant"],"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.role","typeLabel":"enum\u003cstring>"},"structured_answer":{"type":"object","additionalProperties":false,"required":["choice_ids"],"description":"Réponse structurée rapportée dans le delta. Obligatoirement\naccompagnée de `question_id` (le schéma ne porte pas de if/then :\nla règle est appliquée par le runtime, code `invalid_previous_turn`).\n","properties":{"choice_ids":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.structured_answer.choice_ids.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.structured_answer.choice_ids","typeLabel":"string[]"},"free_text":{"type":"string","minLength":1,"maxLength":4000,"description":"Complément libre, autorisé uniquement pour une question `semi_open`.","uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.structured_answer.free_text","typeLabel":"string"}},"isRequired":true,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.structured_answer","typeLabel":"object"},"message_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.message_id","typeLabel":"string"},"question_id":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.question_id","typeLabel":"string"},"text":{"type":"string","minLength":1,"maxLength":8000,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.text","typeLabel":"string"},"occurred_at":{"type":"string","format":"date-time","uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1.occurred_at","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"context_update.oneOf.1.messages.items.[INDEX]","typeLabel":"object"},"description":"Messages nouveaux, dans l'ordre conversationnel.","isRequired":true,"uniqueKey":"context_update.oneOf.1.messages","typeLabel":"object[]"}},"additionalProperties":false,"uniqueKey":"context_update.oneOf.1","typeLabel":"object"}],"uniqueKey":"context_update","typeLabel":"object"},"client_updates":{"type":"object","additionalProperties":false,"minProperties":1,"description":"Mises à jour explicites du système appelant, prioritaires sur l'inférence.","properties":{"data":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","description":"Le client n'envoie jamais de statut. `set` produit une valeur confirmée avec\nla priorité de preuve maximale ; `unset` retire la valeur courante ;\n`not_applicable` satisfait une information de réussite sans lui donner de\nvaleur, par exemple une donnée sans objet pour ce visiteur.\n","required":["id","value"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.id","typeLabel":"string"},"value":{"oneOf":[{"type":"string","description":"Valeur validée contre le schéma publié de l'information de réussite.\nUne chaîne, un nombre, un booléen ou une liste de ces valeurs ; jamais\nun objet, forme que l'extraction ne saurait produire ni corriger.\n","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.0","typeLabel":"string"},{"type":"number","description":"Valeur validée contre le schéma publié de l'information de réussite.\nUne chaîne, un nombre, un booléen ou une liste de ces valeurs ; jamais\nun objet, forme que l'extraction ne saurait produire ni corriger.\n","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.1","typeLabel":"number"},{"type":"boolean","description":"Valeur validée contre le schéma publié de l'information de réussite.\nUne chaîne, un nombre, un booléen ou une liste de ces valeurs ; jamais\nun objet, forme que l'extraction ne saurait produire ni corriger.\n","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.2","typeLabel":"boolean"},{"type":"array","items":{"oneOf":[{"type":"string","uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX].oneOf.0","typeLabel":"string"},{"type":"number","uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX].oneOf.1","typeLabel":"number"},{"type":"boolean","uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX].oneOf.2","typeLabel":"boolean"}],"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX]","typeLabel":"string | number | boolean"},"description":"Valeur validée contre le schéma publié de l'information de réussite.\nUne chaîne, un nombre, un booléen ou une liste de ces valeurs ; jamais\nun objet, forme que l'extraction ne saurait produire ni corriger.\n","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value.oneOf.3","typeLabel":"(string | number | boolean)[]"}],"isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.value","typeLabel":"string | number | boolean | (string | number | boolean)[]"},"operation":{"type":"string","const":"set","default":"set","uniqueKey":"client_updates.data.items.[INDEX].oneOf.0.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"Le client n'envoie jamais de statut. `set` produit une valeur confirmée avec\nla priorité de preuve maximale ; `unset` retire la valeur courante ;\n`not_applicable` satisfait une information de réussite sans lui donner de\nvaleur, par exemple une donnée sans objet pour ce visiteur.\n","required":["id","operation"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.1.id","typeLabel":"string"},"operation":{"type":"string","const":"unset","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.1.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.1","typeLabel":"object"},{"type":"object","description":"Le client n'envoie jamais de statut. `set` produit une valeur confirmée avec\nla priorité de preuve maximale ; `unset` retire la valeur courante ;\n`not_applicable` satisfait une information de réussite sans lui donner de\nvaleur, par exemple une donnée sans objet pour ce visiteur.\n","required":["id","operation"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.2.id","typeLabel":"string"},"operation":{"type":"string","const":"not_applicable","isRequired":true,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.2.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.data.items.[INDEX].oneOf.2","typeLabel":"object"}],"uniqueKey":"client_updates.data.items.[INDEX]","typeLabel":"object"},"uniqueKey":"client_updates.data","typeLabel":"object[]"},"dimensions":{"type":"array","maxItems":100,"items":{"oneOf":[{"type":"object","required":["id","operation","status"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.0.id","typeLabel":"string"},"operation":{"type":"string","const":"set","isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.0.operation","typeLabel":"string"},"status":{"type":"string","enum":["achieved","not_achieved"],"isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.0.status","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","required":["id","operation"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.1.id","typeLabel":"string"},"operation":{"type":"string","const":"exclude","isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.1.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.1","typeLabel":"object"},{"type":"object","required":["id","operation"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.2.id","typeLabel":"string"},"operation":{"type":"string","const":"clear","isRequired":true,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.2.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.dimensions.items.[INDEX].oneOf.2","typeLabel":"object"}],"uniqueKey":"client_updates.dimensions.items.[INDEX]","typeLabel":"object"},"uniqueKey":"client_updates.dimensions","typeLabel":"object[]"},"objective":{"oneOf":[{"type":"object","required":["operation","status"],"properties":{"operation":{"type":"string","const":"set","isRequired":true,"uniqueKey":"client_updates.objective.oneOf.0.operation","typeLabel":"string"},"status":{"type":"string","enum":["achieved","not_achieved"],"isRequired":true,"uniqueKey":"client_updates.objective.oneOf.0.status","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"client_updates.objective.oneOf.0","typeLabel":"object"},{"type":"object","required":["operation"],"properties":{"operation":{"type":"string","const":"clear","isRequired":true,"uniqueKey":"client_updates.objective.oneOf.1.operation","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"client_updates.objective.oneOf.1","typeLabel":"object"}],"uniqueKey":"client_updates.objective","typeLabel":"object"}},"uniqueKey":"client_updates","typeLabel":"object"},"selection":{"type":"object","additionalProperties":false,"description":"Contraintes valables pour cet appel uniquement. Elles sont appliquées **avant**\nle calcul du classement, jamais en filtrant un top 3 déjà constitué.\n","properties":{"candidate_count":{"type":"integer","minimum":1,"maximum":10,"description":"Remplace pour cet appel le nombre de propositions défini dans la configuration.","uniqueKey":"selection.candidate_count","typeLabel":"integer"},"dimensions":{"type":"object","additionalProperties":false,"required":["ids","mode"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"selection.dimensions.ids.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"selection.dimensions.ids","typeLabel":"string[]"},"mode":{"type":"string","enum":["restrict","prefer"],"description":"`restrict` interdit strictement les questions hors de ces dimensions.\n`prefer` les favorise mais autorise un repli si aucun candidat éligible\nn'y reste.\n","isRequired":true,"uniqueKey":"selection.dimensions.mode","typeLabel":"enum\u003cstring>"}},"uniqueKey":"selection.dimensions","typeLabel":"object"},"allowed_question_types":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"string","enum":["open","single_choice","multiple_choice","semi_open"],"description":"- `open` : réponse libre, aucun choix ;\n- `single_choice` : un seul choix parmi la liste ;\n- `multiple_choice` : plusieurs choix possibles ;\n- `semi_open` : choix proposés, complément libre autorisé via\n `structured_answer.free_text`.\n\nPour `semi_open`, `selection_mode` précise si un ou plusieurs choix sont\npermis en plus du complément libre.\n","uniqueKey":"selection.allowed_question_types.items.[INDEX]","typeLabel":"enum\u003cstring>"},"uniqueKey":"selection.allowed_question_types","typeLabel":"enum\u003cstring>[]"},"required_target_ids":{"type":"array","minItems":1,"maxItems":100,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"selection.required_target_ids.items.[INDEX]","typeLabel":"string"},"description":"N'accepter que des questions couvrant au moins une de ces cibles.","uniqueKey":"selection.required_target_ids","typeLabel":"string[]"},"excluded_question_ids":{"type":"array","maxItems":500,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"selection.excluded_question_ids.items.[INDEX]","typeLabel":"string"},"uniqueKey":"selection.excluded_question_ids","typeLabel":"string[]"}},"uniqueKey":"selection","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"premier_tour":{"title":"premier_tour","value":{"state_version":0}},"tour_avec_reponse_libre":{"title":"tour_avec_reponse_libre","value":{"state_version":3,"previous_turn":{"assistant_text":"Et côté budget, vous vous situez plutôt dans quelle fourchette ?","user_text":"Autour de 2 000 euros, je ne veux pas dépasser 2 500.","message_id":"msg_18"}}},"tour_avec_reponse_structuree":{"title":"tour_avec_reponse_structuree","value":{"state_version":4,"previous_turn":{"decision_id":"dec_7f2a","question_id":"q_style","outcome":"asked_answered","structured_answer":{"choice_ids":["choice_contemporain"]}}}},"rattrapage_de_contexte":{"title":"rattrapage_de_contexte","value":{"state_version":5,"context_update":{"mode":"messages","messages":[{"role":"user","message_id":"msg_21","text":"En fait nous avons deux chats qui montent sur le canapé."}]},"client_updates":{"data":[{"id":"has_pets","value":true}]}}},"selection_contrainte":{"title":"selection_contrainte","value":{"state_version":6,"selection":{"candidate_count":2,"allowed_question_types":["single_choice","multiple_choice"],"dimensions":{"ids":["so_besoin"],"mode":"restrict"}}}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"bd52f896-1725-4174-b2e2-c57490985bc7":{"description":"Décision calculée, ou arrêt explicite lorsque la limite de tours est atteinte\nou qu'aucune question n'existe.\n","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["request_id","session_id","decision_id","action","stop_reason","candidates","progress","turn_count","turns_remaining","warnings","degraded","degraded_reasons","versions"],"description":"Aucun score de sélection n'est exposé : le classement est porté par `rank`.\nUn score brut n'a pas de sens métier hors du moteur et ne doit pas devenir\nune dépendance des intégrations.\n\n**Invariants garantis par le moteur**, non exprimés en JSON Schema pour\nrester générables en SDK :\n\n- `action: ask` implique `decision_id` non nul, `stop_reason` nul et au\n moins un candidat ;\n- `action: stop` implique `decision_id` nul, `stop_reason` renseigné et\n `candidates` vide.\n","properties":{"request_id":{"type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"session_id":{"type":"string","isRequired":true,"uniqueKey":"session_id","typeLabel":"string"},"decision_id":{"oneOf":[{"type":"string","description":"Non nul quand `action` vaut `ask`. À renvoyer dans le tour suivant si disponible.","isRequired":true,"uniqueKey":"decision_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Non nul quand `action` vaut `ask`. À renvoyer dans le tour suivant si disponible.","isRequired":true,"uniqueKey":"decision_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"decision_id","typeLabel":"string | null"},"action":{"type":"string","enum":["ask","stop"],"description":"`stop` est produit dans deux cas, précisés par `stop_reason` : la limite\n`max_turns` est atteinte, ou aucune question identifiable n'existe. Un\nobjectif déjà atteint ou une éligibilité normale vide ne coupent pas la\nconversation : le moteur propose encore la meilleure question disponible\net le signale dans `warnings`. Avant la limite de tours, la décision\nd'arrêter appartient à l'appelant.\n","isRequired":true,"uniqueKey":"action","typeLabel":"enum\u003cstring>"},"stop_reason":{"oneOf":[{"type":"string","description":"Cause de l'arrêt :\n\n- `max_turns_reached` : la session a atteint `max_turns`. Le dernier tour\n autorisé est enregistré ; les appels `/next` suivants renvoient le même\n arrêt sans analyser le tour ni modifier la session ;\n- `no_question_available` : aucune question identifiable ne subsiste après\n application des exclusions dures — question inactive, dimension exclu par\n le client, contrainte stricte de l'appel.\n\nLes autres situations terminales remontent par `warnings`, la conversation\nrestant décidée par l'appelant.\n","enum":["no_question_available","max_turns_reached"],"isRequired":true,"uniqueKey":"stop_reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","isRequired":true,"uniqueKey":"stop_reason.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"stop_reason","typeLabel":"enum\u003cstring> | null"},"candidates":{"type":"array","maxItems":10,"items":{"type":"object","additionalProperties":false,"required":["rank","question_id","text","type","choices","target_ids"],"description":"**Invariant garanti par le moteur**, couvert par les tests de contrat :\n`type: open` implique `choices` vide ; tout autre type implique au moins\ndeux choix.\n","properties":{"rank":{"type":"integer","minimum":1,"maximum":10,"isRequired":true,"uniqueKey":"candidates.items.[INDEX].rank","typeLabel":"integer"},"question_id":{"type":"string","minLength":1,"maxLength":128,"description":"Toujours un identifiant valide du corpus publié, y compris pour un repli.","isRequired":true,"uniqueKey":"candidates.items.[INDEX].question_id","typeLabel":"string"},"text":{"type":"string","minLength":1,"maxLength":4000,"description":"Libellé publié de la question. L'agent hôte reste libre de le reformuler :\nZelinqa sait rattacher un texte reformulé à sa question au tour suivant.\n","isRequired":true,"uniqueKey":"candidates.items.[INDEX].text","typeLabel":"string"},"type":{"type":"string","enum":["open","single_choice","multiple_choice","semi_open"],"description":"- `open` : réponse libre, aucun choix ;\n- `single_choice` : un seul choix parmi la liste ;\n- `multiple_choice` : plusieurs choix possibles ;\n- `semi_open` : choix proposés, complément libre autorisé via\n `structured_answer.free_text`.\n\nPour `semi_open`, `selection_mode` précise si un ou plusieurs choix sont\npermis en plus du complément libre.\n","isRequired":true,"uniqueKey":"candidates.items.[INDEX].type","typeLabel":"enum\u003cstring>"},"choices":{"type":"array","maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["choice_id","label"],"properties":{"choice_id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"candidates.items.[INDEX].choices.items.[INDEX].choice_id","typeLabel":"string"},"label":{"type":"string","minLength":1,"maxLength":500,"isRequired":true,"uniqueKey":"candidates.items.[INDEX].choices.items.[INDEX].label","typeLabel":"string"}},"uniqueKey":"candidates.items.[INDEX].choices.items.[INDEX]","typeLabel":"object"},"description":"Vide pour une question ouverte.","isRequired":true,"uniqueKey":"candidates.items.[INDEX].choices","typeLabel":"object[]"},"target_ids":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":128,"uniqueKey":"candidates.items.[INDEX].target_ids.items.[INDEX]","typeLabel":"string"},"description":"Cibles que cette question adresse, principale en premier.","isRequired":true,"uniqueKey":"candidates.items.[INDEX].target_ids","typeLabel":"string[]"},"selection_mode":{"type":"string","enum":["single","multiple"],"description":"Présent pour `semi_open` afin d'indiquer si l'appelant accepte un ou\nplusieurs `choice_ids`. Absent pour les autres types.\n","uniqueKey":"candidates.items.[INDEX].selection_mode","typeLabel":"enum\u003cstring>"}},"uniqueKey":"candidates.items.[INDEX]","typeLabel":"object"},"description":"Ordonnées par pertinence décroissante, rang 1 en premier. Lorsque\nplusieurs candidats sont demandés, le moteur simule la couverture\napportée par le premier avant de choisir le suivant : deux variantes\ndemandant la même information ne sont pas retournées ensemble.\n","isRequired":true,"uniqueKey":"candidates","typeLabel":"object[]"},"progress":{"type":"object","additionalProperties":false,"required":["objective","dimensions"],"properties":{"objective":{"type":"object","additionalProperties":false,"required":["computed_status","progress","client_override","effective_status"],"properties":{"computed_status":{"type":"string","enum":["not_started","in_progress","covered","blocked"],"isRequired":true,"uniqueKey":"progress.objective.computed_status","typeLabel":"enum\u003cstring>"},"progress":{"type":"number","minimum":0,"maximum":1,"description":"Agrégation des dimensions pondérée par leur rôle de complétion. Les\ndimensions exclus sortent du dénominateur.\n","isRequired":true,"uniqueKey":"progress.objective.progress","typeLabel":"number"},"client_override":{"oneOf":[{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["achieved","not_achieved"],"isRequired":true,"uniqueKey":"progress.objective.client_override.oneOf.0.status","typeLabel":"enum\u003cstring>"},"updated_at":{"type":"string","format":"date-time","uniqueKey":"progress.objective.client_override.oneOf.0.updated_at","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"isRequired":true,"uniqueKey":"progress.objective.client_override.oneOf.0","typeLabel":"object"},{"type":"null","isRequired":true,"uniqueKey":"progress.objective.client_override.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"progress.objective.client_override","typeLabel":"object | null"},"effective_status":{"type":"string","enum":["not_started","in_progress","covered","blocked"],"isRequired":true,"uniqueKey":"progress.objective.effective_status","typeLabel":"enum\u003cstring>"}},"isRequired":true,"uniqueKey":"progress.objective","typeLabel":"object"},"dimensions":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","order_position","completion_role","computed_status","progress","client_override","effective_status"],"properties":{"id":{"type":"string","minLength":1,"maxLength":128,"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].id","typeLabel":"string"},"order_position":{"type":"integer","minimum":0,"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].order_position","typeLabel":"integer"},"completion_role":{"type":"string","enum":["blocking","contributing","optional"],"description":"Rôle dans la qualification globale : les données des dimensions blocking doivent être conclues ; une dimension blocking sans donnée ne bloque pas seule la réussite. Les dimensions contributing participent au seuil moyen du niveau. Les dimensions optional n'imposent pas de seuil de couverture, mais les informations de réussite configurées restent exigées, sauf exclusion ou décision explicite du client.","isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].completion_role","typeLabel":"enum\u003cstring>"},"computed_status":{"type":"string","enum":["not_started","in_progress","covered","blocked"],"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].computed_status","typeLabel":"enum\u003cstring>"},"progress":{"type":"number","minimum":0,"maximum":1,"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].progress","typeLabel":"number"},"client_override":{"oneOf":[{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["achieved","not_achieved","excluded"],"description":"`achieved` force la dimension à couvert. `not_achieved` empêche une\ncomplétion calculée prématurée. `excluded` le retire de la sélection et des\ndénominateurs de progression de l'objectif.\n","isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].client_override.oneOf.0.status","typeLabel":"enum\u003cstring>"},"updated_at":{"type":"string","format":"date-time","uniqueKey":"progress.dimensions.items.[INDEX].client_override.oneOf.0.updated_at","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].client_override.oneOf.0","typeLabel":"object"},{"type":"null","isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].client_override.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].client_override","typeLabel":"object | null"},"effective_status":{"type":"string","enum":["not_started","in_progress","covered","blocked","excluded"],"description":"Statut consommable par le client après application de `client_override`\nau `computed_status` : sans override, le statut calculé ; `achieved`\nforce `covered` ; `not_achieved` conserve le statut calculé sauf que\n`covered` redevient `in_progress` ; `excluded` retire la dimension de\nla sélection et des agrégations de l'objectif.\n","isRequired":true,"uniqueKey":"progress.dimensions.items.[INDEX].effective_status","typeLabel":"enum\u003cstring>"}},"uniqueKey":"progress.dimensions.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"progress.dimensions","typeLabel":"object[]"}},"isRequired":true,"uniqueKey":"progress","typeLabel":"object"},"turn_count":{"type":"integer","minimum":0,"isRequired":true,"uniqueKey":"turn_count","typeLabel":"integer"},"turns_remaining":{"type":"integer","minimum":0,"description":"Vaut `0` lorsque la limite de tours est atteinte ; `action` vaut alors `stop`.","isRequired":true,"uniqueKey":"turns_remaining","typeLabel":"integer"},"warnings":{"type":"array","uniqueItems":true,"items":{"type":"string","enum":["objective_achieved","eligibility_exhausted_fallback","constraints_relaxed"],"description":"Conditions d'arrêt réunies, sans que Zelinqa interrompe la conversation.\n\n- `objective_achieved` : les conditions de réussite sont satisfaites ;\n- `eligibility_exhausted_fallback` : plus aucune question n'était éligible\n normalement, la proposition est un repli — elle porte tout de même un\n `question_id` valide et respecte les exclusions dures ;\n- `constraints_relaxed` : une préférence `prefer` a dû être élargie.\n","uniqueKey":"warnings.items.[INDEX]","typeLabel":"enum\u003cstring>"},"isRequired":true,"uniqueKey":"warnings","typeLabel":"enum\u003cstring>[]"},"degraded":{"type":"boolean","description":"Vrai lorsque la compréhension du tour a été effectuée en mode réduit.","isRequired":true,"uniqueKey":"degraded","typeLabel":"boolean"},"degraded_reasons":{"type":"array","uniqueItems":true,"items":{"type":"string","enum":["missing_user_text","summary_only_context","semantic_service_unavailable","unresolved_previous_turn"],"uniqueKey":"degraded_reasons.items.[INDEX]","typeLabel":"enum\u003cstring>"},"isRequired":true,"uniqueKey":"degraded_reasons","typeLabel":"enum\u003cstring>[]"},"versions":{"type":"object","additionalProperties":false,"required":["state_version","engine_version","api_version"],"description":"La version de configuration épinglée par la session n'est pas exposée : le\nclient ne la choisit pas et ne doit pas s'y adosser.\n","properties":{"state_version":{"type":"integer","minimum":0,"description":"À renvoyer dans la mutation suivante de cette session.","isRequired":true,"uniqueKey":"versions.state_version","typeLabel":"integer"},"engine_version":{"type":"string","isRequired":true,"uniqueKey":"versions.engine_version","typeLabel":"string"},"api_version":{"type":"string","const":"1.0","isRequired":true,"uniqueKey":"versions.api_version","typeLabel":"string"}},"isRequired":true,"uniqueKey":"versions","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"decision_normale":{"title":"decision_normale","value":{"request_id":"req_1002","session_id":"ses_01J8Z","decision_id":"dec_7f2a","action":"ask","stop_reason":null,"candidates":[{"rank":1,"question_id":"q_budget","text":"Quel budget souhaitez-vous consacrer au canapé ?","type":"open","choices":[],"target_ids":["annual_budget"]},{"rank":2,"question_id":"q_delai","text":"À quelle période souhaitez-vous être livré ?","type":"single_choice","choices":[{"choice_id":"choice_1m","label":"Dans le mois"},{"choice_id":"choice_3m","label":"Dans les trois mois"},{"choice_id":"choice_later","label":"Plus tard"}],"target_ids":["delivery_window"]}],"progress":{"objective":{"computed_status":"in_progress","progress":0.34,"client_override":null,"effective_status":"in_progress"},"dimensions":[{"id":"so_besoin","order_position":0,"completion_role":"blocking","computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},{"id":"so_budget","order_position":1,"completion_role":"blocking","computed_status":"in_progress","progress":0.15,"client_override":null,"effective_status":"in_progress"},{"id":"so_livraison","order_position":2,"completion_role":"contributing","computed_status":"not_started","progress":0,"client_override":null,"effective_status":"not_started"}]},"turn_count":2,"turns_remaining":8,"warnings":[],"degraded":false,"degraded_reasons":[],"versions":{"state_version":4,"engine_version":"1.0.0","api_version":"1.0"}}},"max_turns_atteint":{"title":"max_turns_atteint","value":{"request_id":"req_1003","session_id":"ses_01J8Z","decision_id":null,"action":"stop","stop_reason":"max_turns_reached","candidates":[],"progress":{"objective":{"computed_status":"in_progress","progress":0.86,"client_override":null,"effective_status":"in_progress"},"dimensions":[{"id":"so_besoin","order_position":0,"completion_role":"blocking","computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},{"id":"so_budget","order_position":1,"completion_role":"blocking","computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},{"id":"so_livraison","order_position":2,"completion_role":"contributing","computed_status":"in_progress","progress":0.4,"client_override":null,"effective_status":"in_progress"}]},"turn_count":10,"turns_remaining":0,"warnings":[],"degraded":false,"degraded_reasons":[],"versions":{"state_version":21,"engine_version":"1.0.0","api_version":"1.0"}}},"arret_sans_question":{"title":"arret_sans_question","value":{"request_id":"req_1004","session_id":"ses_01J8Z","decision_id":null,"action":"stop","stop_reason":"no_question_available","candidates":[],"progress":{"objective":{"computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},"dimensions":[{"id":"so_besoin","order_position":0,"completion_role":"blocking","computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},{"id":"so_budget","order_position":1,"completion_role":"blocking","computed_status":"covered","progress":1,"client_override":null,"effective_status":"covered"},{"id":"so_livraison","order_position":2,"completion_role":"contributing","computed_status":"not_started","progress":0,"client_override":{"status":"excluded","updated_at":"2026-09-01T09:31:00Z"},"effective_status":"excluded"}]},"turn_count":7,"turns_remaining":8,"warnings":["objective_achieved"],"degraded":false,"degraded_reasons":[],"versions":{"state_version":25,"engine_version":"1.0.0","api_version":"1.0"}}}},"exampleType":"examples"}},"exampleType":"examples"},"10515b5b-98e1-4a18-8125-95c38a75fc93":{"description":"Réponse 401 possible au niveau de l'application. Une clé absente ou invalide est généralement refusée en 403 par la passerelle, sans enveloppe métier garantie.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"unauthorized","message":"Clé d'intégration absente ou invalide.","request_id":"req_9000","details":{}},"examples":{"Example":{"title":"Example","value":{"code":"unauthorized","message":"Clé d'intégration absente ou invalide.","request_id":"req_9000","details":{}}}},"exampleType":"examples"}},"exampleType":"examples"},"b335d75a-5676-4fc4-bccf-1dd816757d15":{"description":"Accès refusé. La passerelle peut renvoyer 403 pour une clé absente, invalide, expirée, révoquée ou dépourvue du scope requis, sans enveloppe métier garantie.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"insufficient_scope","message":"Cette clé ne permet pas de publier une configuration.","request_id":"req_9001","details":{"required_scopes":["configuration:publish"],"granted_scopes":["configuration:read","configuration:write"]}},"examples":{"Example":{"title":"Example","value":{"code":"insufficient_scope","message":"Cette clé ne permet pas de publier une configuration.","request_id":"req_9001","details":{"required_scopes":["configuration:publish"],"granted_scopes":["configuration:read","configuration:write"]}}}},"exampleType":"examples"}},"exampleType":"examples"},"9c610e69-6c40-4aa1-9f5e-6ca48fe94c96":{"description":"Session inconnue, ou appartenant à un autre tenant.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"unknown_session","message":"La session demandée est inconnue.","request_id":"req_9007","details":{"session_id":"ses_inconnue"}},"examples":{"Example":{"title":"Example","value":{"code":"unknown_session","message":"La session demandée est inconnue.","request_id":"req_9007","details":{"session_id":"ses_inconnue"}}}},"exampleType":"examples"}},"exampleType":"examples"},"20c78f34-4862-4533-a674-9f516b85197f":{"description":"Conflit de version optimiste ou réutilisation d'une clé d'idempotence.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"state_version_conflict":{"title":"state_version_conflict","value":{"code":"state_version_conflict","message":"La session a été modifiée depuis votre dernière lecture.","request_id":"req_9003","details":{"supplied_state_version":7,"current_state_version":8}}},"idempotency_key_reused":{"title":"idempotency_key_reused","value":{"code":"idempotency_key_reused","message":"Cette clé d'idempotence est déjà associée à une autre requête.","request_id":"req_9004","details":{"idempotency_key":"next-ses01J8Z-turn-4"}}}},"exampleType":"examples"}},"exampleType":"examples"},"d8f18170-f16a-4543-931a-b9b8b1f539e8":{"description":"L'artefact compilé épinglé par la session est réellement inaccessible. Une\nconfiguration simplement remplacée par une version plus récente ne produit pas\ncette erreur : l'ancienne version reste lisible pour terminer les sessions qui\nl'utilisent déjà.\n","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"compiled_artifact_unavailable","message":"L'artefact moteur de cette session est temporairement indisponible.","request_id":"req_9010","details":{"session_id":"ses_01J8Z"}},"examples":{"Example":{"title":"Example","value":{"code":"compiled_artifact_unavailable","message":"L'artefact moteur de cette session est temporairement indisponible.","request_id":"req_9010","details":{"session_id":"ses_01J8Z"}}}},"exampleType":"examples"}},"exampleType":"examples"},"f3065aa6-e157-46a2-af6d-77c3656d45b7":{"description":"Le tour précédent est incohérent ou les contraintes strictes ne laissent aucune question. Une question ouverte répondue sans previous_turn.user_text non vide renvoie 422 invalid_previous_turn avant toute analyse par modèle.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"open_question_without_text":{"title":"open_question_without_text","value":{"code":"invalid_previous_turn","message":"une question ouverte répondue exige user_text","request_id":"req_open_without_text","details":{}}},"invalid_previous_turn":{"title":"invalid_previous_turn","value":{"code":"invalid_previous_turn","message":"Les identifiants fournis ne correspondent pas à la décision en attente.","request_id":"req_9011","details":{"pending_decision_id":"dec_7f2a","supplied_decision_id":"dec_7f29","supplied_question_id":"q_budget","candidate_question_ids":["q_style","q_budget","q_delai"]}}},"constraint_no_match":{"title":"constraint_no_match","value":{"code":"constraint_no_match","message":"Aucune question disponible ne satisfait les contraintes demandées.","request_id":"req_9012","details":{"allowed_question_types":["multiple_choice"],"required_target_ids":["annual_budget"]}}},"invalid_choice":{"title":"invalid_choice","value":{"code":"invalid_choice","message":"Un choix fourni ne correspond pas à la question résolue.","request_id":"req_9013","details":{"question_id":"q_style","invalid_choice_ids":["choice_inconnu"]}}}},"exampleType":"examples"}},"exampleType":"examples"},"99ef41a4-e22a-4187-8a24-2aab609d3c70":{"description":"La clé d'idempotence n'a pas pu être réservée après deux tentatives, à cause\nd'un cycle anormal de requêtes concurrentes portant la même clé.\n\nCe n'est **pas** une erreur du client et ce n'est pas un conflit : réessayer\naprès un court délai a des chances d'aboutir. À distinguer de\n`idempotency_key_reused`, qui est définitif pour ce couple clé/corps.\n","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","message","request_id","details"],"description":"Enveloppe uniforme de toutes les erreurs métier.","properties":{"code":{"type":"string","description":"Catalogue fermé des erreurs métier V1.","enum":["unauthorized","insufficient_scope","idempotency_contention","state_version_conflict","idempotency_key_reused","unknown_session","invalid_previous_turn","constraint_no_match","invalid_choice","compiled_artifact_unavailable","configuration_validation_failed","compilation_in_progress","unknown_configuration","unknown_compilation"],"isRequired":true,"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","additionalProperties":true,"isRequired":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"idempotency_contention","message":"La clé d'idempotence n'a pas pu être réservée, réessayez.","request_id":"req_9017","details":{"idempotency_key":"next-ses01J8Z-turn-4","retry_after_seconds":1}},"examples":{"Example":{"title":"Example","value":{"code":"idempotency_contention","message":"La clé d'idempotence n'a pas pu être réservée, réessayez.","request_id":"req_9017","details":{"idempotency_key":"next-ses01J8Z-turn-4","retry_after_seconds":1}}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"9a21f59e-73e7-40cb-aed4-69ae805ab1b8":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"Zelinqa API key","description":"Envoyez la clé API dans Authorization: Bearer \u003cclé>. Elle identifie le domaine et les droits autorisés. Ne transmettez pas d'en-têtes d'identité internes.","scopes":[],"schemeName":"ApiKeyAuth"}}},"servers":{"1a6b3648-7307-43a6-aa3e-c2fc73c4533a":{"url":"https://api.zelinqa.ai","description":"API publique Zelinqa"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"Zelinqa API key","description":"Envoyez la clé API dans Authorization: Bearer \u003cclé>. Elle identifie le domaine et les droits autorisés. Ne transmettez pas d'en-têtes d'identité internes.","scopes":[],"schemeName":"ApiKeyAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Envoyez la clé API dans Authorization: Bearer \u003cclé>. Elle identifie le domaine et les droits autorisés. Ne transmettez pas d'en-têtes d'identité internes.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"ApiKeyAuth","name":"Authorization"}],"title":"ApiKeyAuth"}]},"originalFileLocation":"openapi.fr.yaml"},"subdomain":"zelinqa-d77427f3","siteName":"Zelinqa","title":"Comprendre le tour précédent et proposer les questions suivantes - Zelinqa","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"fr":{"href":"/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes","matchLevel":0},"en":{"href":"/en/introduction","matchLevel":4}}},"lastModified":"2026-10-18T22:01:15.186Z","originalFileLocation":"api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes.mdx","locale":"fr"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Route principale du runtime. En un seul appel, le moteur résout la question réellement posée et son outcome, applique les mises à jour du client, réduit l\u0026#x27;état, recalcule les progressions, puis classe les questions éligibles. Le client n\u0026#x27;a pas à savoir quelle candidate son agent a utilisée : si decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis la décision en attente, le texte de l\u0026#x27;agent, la réponse structurée et le contexte. Une reformulation de la question par l\u0026#x27;agent hôte reste rattachable. Au premier appel d\u0026#x27;une session neuve, previous_turn est absent. Lorsque previous_turn répond à la dernière question autorisée par max_turns, ce tour est enregistré puis la réponse est action: stop avec stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt. /events peut remplacer la décision en attente après que l\u0026#x27;agent hôte a déjà posé sa question. Une réponse dont previous_turn.decision_id désigne la dernière décision remplacée est donc acceptée jusqu\u0026#x27;au prochain /next abouti : - si previous_turn.question_id figure encore parmi les candidates de la décision courante, la réponse lui est rattachée normalement ; - sinon, previous_turn est lu comme un contexte en mode messages : les données qu\u0026#x27;il contient sont extraites, aucun outcome n\u0026#x27;est enregistré pour la question retirée et aucun tour n\u0026#x27;est consommé. La réponse renvoie la décision courante, avec le même decision_id, si la sélection la redonne à l\u0026#x27;identique, et sinon une nouvelle décision. Un decision_id qui ne désigne ni la décision en attente ni la dernière décision remplacée reste refusé en invalid_previous_turn.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Zelinqa\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Comprendre le tour précédent et proposer les questions suivantes - Zelinqa\">\u003cmeta data-mint-head property=\"og:description\" content=\"Route principale du runtime. En un seul appel, le moteur résout la question réellement posée et son outcome, applique les mises à jour du client, réduit l\u0026#x27;état, recalcule les progressions, puis classe les questions éligibles. Le client n\u0026#x27;a pas à savoir quelle candidate son agent a utilisée : si decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis la décision en attente, le texte de l\u0026#x27;agent, la réponse structurée et le contexte. Une reformulation de la question par l\u0026#x27;agent hôte reste rattachable. Au premier appel d\u0026#x27;une session neuve, previous_turn est absent. Lorsque previous_turn répond à la dernière question autorisée par max_turns, ce tour est enregistré puis la réponse est action: stop avec stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt. /events peut remplacer la décision en attente après que l\u0026#x27;agent hôte a déjà posé sa question. Une réponse dont previous_turn.decision_id désigne la dernière décision remplacée est donc acceptée jusqu\u0026#x27;au prochain /next abouti : - si previous_turn.question_id figure encore parmi les candidates de la décision courante, la réponse lui est rattachée normalement ; - sinon, previous_turn est lu comme un contexte en mode messages : les données qu\u0026#x27;il contient sont extraites, aucun outcome n\u0026#x27;est enregistré pour la question retirée et aucun tour n\u0026#x27;est consommé. La réponse renvoie la décision courante, avec le même decision_id, si la sélection la redonne à l\u0026#x27;identique, et sinon une nouvelle décision. Un decision_id qui ne désigne ni la décision en attente ni la dernière décision remplacée reste refusé en invalid_previous_turn.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Zelinqa\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://zelinqa-d77427f3.mintlify.site/_mintlify/api/og/v2?division=Sessions\u0026amp;title=Comprendre+le+tour+pr%C3%A9c%C3%A9dent+et+proposer+les+questions+suivantes\u0026amp;description=Route+principale+du+runtime.+En+un+seul+appel%2C+le+moteur+r%C3%A9sout+la+question%0Ar%C3%A9ellement+pos%C3%A9e+et+son+outcome%2C+applique+les+mises+%C3%A0+jour+du+client%2C+r%C3%A9duit%0Al%27%C3%A9tat%2C\u0026amp;theme=2bd94d4ac999925d0fca8b51\u0026amp;signature=4bab0a3cd987be30438ffad0cbcc615aebc63cb8ad73f7bac2ab737cbf691194\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Comprendre le tour précédent et proposer les questions suivantes - Zelinqa\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Route principale du runtime. En un seul appel, le moteur résout la question réellement posée et son outcome, applique les mises à jour du client, réduit l\u0026#x27;état, recalcule les progressions, puis classe les questions éligibles. Le client n\u0026#x27;a pas à savoir quelle candidate son agent a utilisée : si decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis la décision en attente, le texte de l\u0026#x27;agent, la réponse structurée et le contexte. Une reformulation de la question par l\u0026#x27;agent hôte reste rattachable. Au premier appel d\u0026#x27;une session neuve, previous_turn est absent. Lorsque previous_turn répond à la dernière question autorisée par max_turns, ce tour est enregistré puis la réponse est action: stop avec stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt. /events peut remplacer la décision en attente après que l\u0026#x27;agent hôte a déjà posé sa question. Une réponse dont previous_turn.decision_id désigne la dernière décision remplacée est donc acceptée jusqu\u0026#x27;au prochain /next abouti : - si previous_turn.question_id figure encore parmi les candidates de la décision courante, la réponse lui est rattachée normalement ; - sinon, previous_turn est lu comme un contexte en mode messages : les données qu\u0026#x27;il contient sont extraites, aucun outcome n\u0026#x27;est enregistré pour la question retirée et aucun tour n\u0026#x27;est consommé. La réponse renvoie la décision courante, avec le même decision_id, si la sélection la redonne à l\u0026#x27;identique, et sinon une nouvelle décision. Un decision_id qui ne désigne ni la décision en attente ni la dernière décision remplacée reste refusé en invalid_previous_turn.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://zelinqa-d77427f3.mintlify.site/_mintlify/api/og/v2?division=Sessions\u0026amp;title=Comprendre+le+tour+pr%C3%A9c%C3%A9dent+et+proposer+les+questions+suivantes\u0026amp;description=Route+principale+du+runtime.+En+un+seul+appel%2C+le+moteur+r%C3%A9sout+la+question%0Ar%C3%A9ellement+pos%C3%A9e+et+son+outcome%2C+applique+les+mises+%C3%A0+jour+du+client%2C+r%C3%A9duit%0Al%27%C3%A9tat%2C\u0026amp;theme=2bd94d4ac999925d0fca8b51\u0026amp;signature=4bab0a3cd987be30438ffad0cbcc615aebc63cb8ad73f7bac2ab737cbf691194\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/zelinqa-d77427f3/DJdTp2ipwe2o2XTM/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Zelinqa\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#7C3AED\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.zelinqa.ai/#organization\",\"name\":\"Zelinqa\",\"url\":\"https://docs.zelinqa.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/zelinqa-d77427f3/NHQX6jXz7QClMoqF/logo/light.svg?fit=max\u0026auto=format\u0026n=NHQX6jXz7QClMoqF\u0026q=85\u0026s=6cbe3336a207008182be0916b85b70ef\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.zelinqa.ai#website\",\"name\":\"Zelinqa\",\"url\":\"https://docs.zelinqa.ai\",\"publisher\":{\"@id\":\"https://docs.zelinqa.ai/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes#webpage\",\"url\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes\",\"name\":\"Comprendre le tour précédent et proposer les questions suivantes\",\"description\":\"Route principale du runtime. En un seul appel, le moteur résout la question réellement posée et son outcome, applique les mises à jour du client, réduit l'état, recalcule les progressions, puis classe les questions éligibles. Le client n'a pas à savoir quelle candidate son agent a utilisée : si decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis la décision en attente, le texte de l'agent, la réponse structurée et le contexte. Une reformulation de la question par l'agent hôte reste rattachable. Au premier appel d'une session neuve, previous_turn est absent. Lorsque previous_turn répond à la dernière question autorisée par max_turns, ce tour est enregistré puis la réponse est action: stop avec stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt. /events peut remplacer la décision en attente après que l'agent hôte a déjà posé sa question. Une réponse dont previous_turn.decision_id désigne la dernière décision remplacée est donc acceptée jusqu'au prochain /next abouti : - si previous_turn.question_id figure encore parmi les candidates de la décision courante, la réponse lui est rattachée normalement ; - sinon, previous_turn est lu comme un contexte en mode messages : les données qu'il contient sont extraites, aucun outcome n'est enregistré pour la question retirée et aucun tour n'est consommé. La réponse renvoie la décision courante, avec le même decision_id, si la sélection la redonne à l'identique, et sinon une nouvelle décision. Un decision_id qui ne désigne ni la décision en attente ni la dernière décision remplacée reste refusé en invalid_previous_turn.\",\"dateModified\":\"2026-10-18T22:01:15.186Z\",\"isPartOf\":{\"@id\":\"https://docs.zelinqa.ai#website\"},\"breadcrumb\":{\"@id\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Sessions\",\"item\":\"https://docs.zelinqa.ai/api-reference/sessions/cr%C3%A9er-une-session\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Comprendre le tour précédent et proposer les questions suivantes\",\"item\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes#apireference\",\"headline\":\"Comprendre le tour précédent et proposer les questions suivantes\",\"name\":\"Comprendre le tour précédent et proposer les questions suivantes\",\"description\":\"Route principale du runtime. En un seul appel, le moteur résout la question réellement posée et son outcome, applique les mises à jour du client, réduit l'état, recalcule les progressions, puis classe les questions éligibles. Le client n'a pas à savoir quelle candidate son agent a utilisée : si decision_id, question_id ou outcome sont absents, Zelinqa les résout depuis la décision en attente, le texte de l'agent, la réponse structurée et le contexte. Une reformulation de la question par l'agent hôte reste rattachable. Au premier appel d'une session neuve, previous_turn est absent. Lorsque previous_turn répond à la dernière question autorisée par max_turns, ce tour est enregistré puis la réponse est action: stop avec stop_reason: max_turns_reached. Les appels suivants renvoient le même arrêt. /events peut remplacer la décision en attente après que l'agent hôte a déjà posé sa question. Une réponse dont previous_turn.decision_id désigne la dernière décision remplacée est donc acceptée jusqu'au prochain /next abouti : - si previous_turn.question_id figure encore parmi les candidates de la décision courante, la réponse lui est rattachée normalement ; - sinon, previous_turn est lu comme un contexte en mode messages : les données qu'il contient sont extraites, aucun outcome n'est enregistré pour la question retirée et aucun tour n'est consommé. La réponse renvoie la décision courante, avec le même decision_id, si la sélection la redonne à l'identique, et sinon une nouvelle décision. Un decision_id qui ne désigne ni la décision en attente ni la dernière décision remplacée reste refusé en invalid_previous_turn.\",\"url\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes\",\"mainEntityOfPage\":{\"@id\":\"https://docs.zelinqa.ai/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes#webpage\"},\"dateModified\":\"2026-10-18T22:01:15.186Z\",\"publisher\":{\"@id\":\"https://docs.zelinqa.ai/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.zelinqa.ai#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Zelinqa\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Zelinqa\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/sessions/comprendre-le-tour-pr%C3%A9c%C3%A9dent-et-proposer-les-questions-suivantes.md","siteName":"Zelinqa","nav":{"global":null,"languages":[{"language":"fr","default":true,"tabs":[{"tab":"Développeurs","pages":[{"title":"Développeurs","href":"/fr/introduction"}]},{"tab":"Zelinqa Studio","pages":[{"title":"Zelinqa Studio","href":"/fr/studio/overview"}]},{"tab":"Référence API","groups":[{"group":"Guides API","pages":[{"title":"Référence API V1","href":"/fr/api-reference/overview"},{"title":"Authentification, idempotence et concurrence","href":"/fr/api-reference/auth-concurrency"},{"title":"Intégration REST","href":"/fr/integrations/rest-api"},{"title":"Appels HTTP avec curl","href":"/fr/quickstart/first-api-call"},{"title":"Erreurs","href":"/fr/api-reference/errors"}]},{"group":"Sessions","pages":[{"title":"Créer une session","description":"Crée une session attachée à la version publiée active. La première question est obtenue ensuite avec POST /v1/sessions/{session_id}/next. initial_history permet de reprendre une conversation déjà commencée.","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions","href":"/api-reference/sessions/créer-une-session"},{"title":"Comprendre le tour précédent et proposer les questions suivantes","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions/{session_id}/next","href":"/api-reference/sessions/comprendre-le-tour-précédent-et-proposer-les-questions-suivantes"},{"title":"Appliquer un contexte ou une mise à jour sans consommer de tour","description":"Même réducteur que `/next`, sans consommer de tour. Sert à rattraper des\nmessages qui n'ont pas transité par Zelinqa, synchroniser une donnée déjà connue\ndu système appelant, corriger une valeur, ou piloter une dimension.\n\nLe contexte fourni peut résoudre la décision en attente lorsqu'il y répond sans\nambiguïté ; `pending_decision` vaut alors `null` et le prochain `/next` propose\nla suite. Sinon, la décision en attente est recalculée sur l'état mis à jour,\navec les contraintes `selection` du `/next` qui l'a proposée, sans appel à un\nmodèle :\n- même liste de candidates : la décision et son `decision_id` sont conservés ;\n- liste différente : `pending_decision` porte une nouvelle décision, avec un\n nouveau `decision_id`. C'est elle que l'agent hôte doit poser. Par exemple,\n une donnée confirmée par `client_updates` pour la question en attente retire\n cette question ;\n- plus aucune question disponible : la session s'arrête (`status: stopped`),\n comme un `/next` qui répondrait `stop_reason: no_question_available`. Si\n seules les contraintes `selection` d'origine ne laissent plus de question,\n `pending_decision` vaut `null`, la session reste active et le prochain\n `/next` choisit avec ses propres contraintes.\n\nLorsque la limite `max_turns` est atteinte, la session s'arrête et\n`pending_decision` vaut `null`.\n\nUne réponse à une décision ainsi remplacée reste acceptée par `/next` : voir\n`previous_turn.decision_id`.\n","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions/{session_id}/events","href":"/api-reference/sessions/appliquer-un-contexte-ou-une-mise-à-jour-sans-consommer-de-tour"},{"title":"Lire l'état public d'une session","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/sessions/{session_id}","href":"/api-reference/sessions/lire-létat-public-dune-session"},{"title":"Déclarer le résultat réel de la conversation","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/sessions/{session_id}/feedback","href":"/api-reference/sessions/déclarer-le-résultat-réel-de-la-conversation"}]},{"group":"Configuration","pages":[{"title":"Lire la configuration éditoriale","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/configuration","href":"/api-reference/configuration/lire-la-configuration-éditoriale"},{"title":"Lister les questions","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/configuration/questions","href":"/api-reference/configuration/lister-les-questions"},{"title":"Consulter le journal des changements","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/configuration/audit","href":"/api-reference/configuration/consulter-le-journal-des-changements"},{"title":"Appliquer des changements au brouillon","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/configuration/changes","href":"/api-reference/configuration/appliquer-des-changements-au-brouillon"},{"title":"Publier le brouillon","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml post /v1/configuration/publish","href":"/api-reference/configuration/publier-le-brouillon"},{"title":"Suivre un job de compilation","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/configuration/compilations/{compilation_id}","href":"/api-reference/configuration/suivre-un-job-de-compilation"}]},{"group":"Service","pages":[{"title":"Sonde de disponibilité","deprecated":null,"version":null,"openapi":"/openapi.fr.yaml get /v1/health","href":"/api-reference/legacy/sonde-de-disponibilité"}]}]}]},{"language":"en","pages":[{"title":"en","href":"/en/introduction"}]}]},"basePath":"","title":"Comprendre le tour précédent et proposer les questions suivantes - Zelinqa","buildId":"dpl_G2Qd45vZZ7MkBiGF9yYx8ZsbbKXX","deploymentId":"dpl_G2Qd45vZZ7MkBiGF9yYx8ZsbbKXX","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-NXj-Rqjv.js","utils-m0thOP-_.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-D13EKcfm.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema--XTdfsEb.js","snippetPresets-D3s4lmAH.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-ChURybxL.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-DL8CiXq2.js","shallow-DI2-YB2E.js","getApiPlaygroundDisplay-DxbW7b_y.js","CodeSnippet-CiNYS0pP.js","CodeSnippets-BT87bThu.js","Page-DSpdRuhM.js","getPastedJson-F_g_IrFQ.js","icon-CCIG5BAs.js","MethodPill-DY3E0jwx.js","DuplicateIcon-BN88xnEg.js","createIcon-VCCc5HO5.js","DynamicMarkdown-CaSwclgK.js","SectionHeading-DXV8nWhc.js","axios-vUo_bRtp.js","Markdown-CV32Re6G.js","clsx-5ydLOnhV.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-pFDdfjRe.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-BUGO5bPJ.js"]}