MCP Example 3 - Loan Application Extended
This is the confirmation-first version of the loan flow built around the newer runtime behavior:
CorrectionStephandles confirmation affirmations and in-place editsPOST_DIALOGUE_ACTcan override guarded dialogue-act output before interaction policy runsPOST_SCHEMA_EXTRACTIONmoves the flow into confirmation once required data is completePRE_AGENT_MCPdelays MCP until the user explicitly confirmsSET_INPUT_PARAMcan mark confirmation runtime flags without extra Java codeSET_DIALOGUE_ACTcan safely promote an LLM candidate act (for exampleEDIT) back into the finaldialogue_actConvEngineVerboseAdapter/ce_verbosecan emit custom progress messages for the confirm-and-process path
This is the recommended state machine for the extended loan workflow:
IDLE -> ELIGIBILITY_GATE -> CONFIRMATION -> PROCESS_APPLICATION -> COMPLETED
The current convengine-demo mcp_planner_seed.sql still scopes the loan planner and tools to ELIGIBILITY_GATE and closes directly to COMPLETED. It does not yet model CONFIRMATION and PROCESS_APPLICATION. This example shows the missing shape to add.
Flow summary
State flow
| State | Purpose | What happens here |
|---|---|---|
| IDLE | Loan intake entry | Intent is recognized; rule moves into ELIGIBILITY_GATE. |
| ELIGIBILITY_GATE | Required field collection | Schema extraction collects customerId, requestedAmount, tenureMonths. |
| CONFIRMATION | User review | Show exact collected values; allow AFFIRM or EDIT. |
| PROCESS_APPLICATION | MCP execution | Planner runs credit -> fraud -> debt -> submit in sequence. |
| COMPLETED | Final answer | Derived response uses context.mcp.finalAnswer as the primary summary. |
- Chat + Trace
- Step Graph
- Component Tables
- Complete SQL
- Expected Conversation
Extended loan confirmation-first flow
IDLE -> ELIGIBILITY_GATE -> CONFIRMATION -> PROCESS_APPLICATION -> COMPLETED
Table usage by phase
| Phase | Reads | Writes | Why it matters |
|---|---|---|---|
| Intent bootstrap | ce_intent_classifier, ce_rule | ce_audit | Classifier starts in IDLE; rules move into ELIGIBILITY_GATE. |
| Schema collection | ce_output_schema, ce_prompt_template, ce_response | ce_audit | Collect and ask only for missing fields. |
| Schema complete gate | ce_rule | ce_audit | POST_SCHEMA_EXTRACTION moves to CONFIRMATION and can set runtime flags. |
| Confirmation response | ce_response, ce_prompt_template | ce_audit | Shows exact collected values before any MCP call. |
| Correction path | session/context, optional ce_verbose | ce_audit | Patch only the changed field and stay in CONFIRMATION. |
| Pre-MCP gate | ce_rule | ce_audit | PRE_AGENT_MCP checks routing_decision and unlocks PROCESS_APPLICATION. |
| Planner + tools | ce_mcp_planner, ce_mcp_tool | ce_audit | Run the credit/fraud/debt/submit chain only after confirmation. |
| Post-MCP close | ce_rule | ce_audit | POST_AGENT_MCP moves PROCESS_APPLICATION -> COMPLETED. |
| Final response | ce_response, ce_prompt_template | ce_conversation, ce_audit | Return the final derived summary from context.mcp.finalAnswer. |
What is missing from the current demo seed
| Current seed | Missing piece | Needed for this example |
|---|---|---|
| Classifier starts LOAN_APPLICATION in ELIGIBILITY_GATE | No clean IDLE intake entry | Classifier starts in IDLE, then POST_AGENT_INTENT advances. |
| Planner scoped to ELIGIBILITY_GATE | Runs too early | Planner row should be scoped to PROCESS_APPLICATION. |
| Tools scoped to ELIGIBILITY_GATE | APIs can run before confirmation | Tool rows should be scoped to PROCESS_APPLICATION. |
| POST_AGENT_MCP closes ELIGIBILITY_GATE -> COMPLETED | No confirmation checkpoint | Add CONFIRMATION and PROCESS_APPLICATION phases in between. |
| No confirmation prompt row | No explicit user review step | Add CONFIRMATION TEXT prompt + response. |
| No PRE_AGENT_MCP confirmation rule | No confirm-before-run gate | Route only after routing_decision=PROCEED_CONFIRMED. |
Expected next conversation
| Turn | User / System | Expected behavior |
|---|---|---|
| 1 | User: Hi | Intent GREETING, state IDLE, normal greeting response. |
| 2 | User: I need a loan for my customer | Intent LOAN_APPLICATION, POST_AGENT_INTENT moves to ELIGIBILITY_GATE, ask for missing fields. |
| 3 | User: customer id 1234, 35000, 24 months | Schema extraction fills all required fields, POST_SCHEMA_EXTRACTION moves to CONFIRMATION. |
| 4 | Assistant | Please confirm: customerId 1234, requestedAmount 35000, tenureMonths 24. Proceed? |
| 5 | User: Ohh wait, I missed one zero. Change amount to 350000. | DialogueAct=EDIT, CorrectionStep patches requestedAmount only, stays in CONFIRMATION. |
| 6 | Assistant | Updated. Please confirm: customerId 1234, requestedAmount 350000, tenureMonths 24. Proceed? |
| 7 | User: Looks good, go ahead. | DialogueAct=AFFIRM, routing_decision=PROCEED_CONFIRMED, PRE_AGENT_MCP moves to PROCESS_APPLICATION. |
| 8 | System internal | Planner runs credit -> fraud -> debt -> submit in order. |
| 9 | Assistant final | POST_AGENT_MCP moves to COMPLETED and returns the final loan summary. |
For the exact phrase “I missed one zero, it is 350000”, the cleanest path is:
DialogueActStepkeeps the LLM candidate asdialogue_act_llm_candidate=EDITPOST_DIALOGUE_ACTcan useSET_DIALOGUE_ACTto restoreEDITif the guarded final result stayedNEW_REQUESTCorrectionSteppatches the field in place
Explicit forms like “change amount to 350000” are still the most reliable with the current deterministic patch path.
Why this flow is the recommended pattern
This example exists to solve two common problems cleanly:
- “I need rules after schema extraction, but before MCP starts.”
- “I asked for confirmation, the user said yes, and I do not want to run schema extraction again.”
The correct answer is not “stuff more prompt context into every turn.” The correct answer is to treat the turn type as a routing decision.
Post-schema, pre-MCP control points
Use both phases, but for different reasons:
Why both rule phases exist
| Phase | When it runs | Use it for |
|---|---|---|
| POST_SCHEMA_EXTRACTION | Immediately after schema merge and schemaComplete recompute | Move to CONFIRMATION, set confirmation flags, seed lightweight runtime variables. |
| PRE_AGENT_MCP | At the start of MCP execution, just before planner/tool logic | Final gate for starting MCP, changing state, or skipping MCP entirely. |
In this loan flow:
POST_SCHEMA_EXTRACTIONseesschemaComplete=true- it sets
state=CONFIRMATION - the active
ce_prompt_templateforCONFIRMATIONshould useinteraction_mode=CONFIRM - optional
interaction_contractcan allowaffirm,edit, andreset - optional
POST_DIALOGUE_ACTrule withSET_DIALOGUE_ACTrestores guarded LLMEDITbefore interaction policy runs - user replies
CorrectionStepinterprets the reply from prompt-template interaction metadataPRE_AGENT_MCPdecides whether MCP should start
That is the clean way to run rules after schema extraction but before MCP.
How confirmation turns should work
When the engine asks:
Please confirm: customerId 1234, requestedAmount 350000, tenureMonths 24. Proceed?
the next user turn should not be treated like a fresh extraction request.
Use this shape instead:
DialogueActStepnormalizesyes,go ahead,please do it,looks goodintoAFFIRMCorrectionStepchecks the active prompt template (interaction_mode=CONFIRM) plus dialogue act- if the active template allows affirm and dialogue act is
AFFIRM, it sets a routing flag such asrouting_decision=PROCEED_CONFIRMED - downstream steps skip expensive or unnecessary work
This is why DialogueActStep is crucial: rules should match on the normalized signal, not raw free-form text.
How to apply rules on “yes”, “go ahead”, and similar replies
Do not write ce_rule against raw strings like:
yesgo aheadconfirm
That is fragile and ambiguous.
Use a scoped runtime pattern:
Confirmation interaction pattern
| Variable | Who sets it | Why it exists |
|---|---|---|
| interaction_mode | ce_prompt_template | Marks that this turn is a confirmation checkpoint. |
| interaction_contract | ce_prompt_template | Declares allowed capabilities such as affirm/edit/reset. |
| routing_decision | CorrectionStep | Normalizes the next branch, for example PROCEED_CONFIRMED. |
| skip_schema_extraction | CorrectionStep or later rule | Prevents another schema extraction call for confirm-accept turns. |
| correction_applied | CorrectionStep | Lets confirmation response explain that a value was updated. |
Then your rules can check:
- current
state - active prompt-template
interaction_mode - active prompt-template
interaction_contract dialogue_actinputParams.routing_decision
That is much safer than parsing raw “yes” in SQL.
How retry should work after MCP failure
If an MCP call fails in PROCESS_APPLICATION, the flow should stay in PROCESS_APPLICATION, not jump to COMPLETED.
Use this shape:
POST_AGENT_MCPcompletion rule matches only whencontext.mcp.lifecycle.finished == trueandcontext.mcp.lifecycle.error == false- the
PROCESS_APPLICATIONprompt template usesinteraction_mode=PROCESSING - the
PROCESS_APPLICATIONinteraction_contractincludesretry CorrectionStepdetects retry phrases likeretry,try again, andagain- it sets
routing_decision=RETRY_IN_PLACE,skip_intent_resolution=true, andskip_schema_extraction=true McpToolStepthen runs again in the same state and re-calls the API
That gives you deterministic retry behavior without depending on state-name parsing or arbitrary runtime flags.
How to avoid another schema extraction call
This is the key optimization.
When the user has already supplied:
customerIdrequestedAmounttenureMonths
and the engine is already in CONFIRMATION, a reply like:
Looks good, go ahead.
should not trigger a full schema extraction again.
Recommended behavior:
DialogueActStepreturnsAFFIRMCorrectionStepsees an active confirmation prompt (interaction_mode=CONFIRM)- it sets
routing_decision=PROCEED_CONFIRMED - it also sets
skip_schema_extraction=true SchemaExtractionStepis skippedPRE_AGENT_MCPseesrouting_decision=PROCEED_CONFIRMEDand moves toPROCESS_APPLICATION
That avoids:
- one more LLM call
- redundant re-parsing of already-collected data
- accidental mutation of existing schema values
How partial edits should work
When the user says:
Ohh wait, I missed one zero. Change amount to 350000.
the engine should not perform a full schema extraction from scratch.
Recommended CorrectionStep behavior:
- detect
dialogue_act=EDIT - inspect existing schema in
context - patch only the changed field (
requestedAmount) - keep untouched fields (
customerId,tenureMonths) - recompute schema completeness
- stay in
CONFIRMATION - set:
correction_applied=truecorrection_target_field=requestedAmountskip_schema_extraction=true
Then the assistant re-renders the confirmation view with only the changed value updated.
That is exactly why this example uses:
CONFIRMATIONas a dedicated stateCorrectionStepbefore reworkSET_INPUT_PARAMfor lightweight runtime flagsSET_DIALOGUE_ACTfor safe post-classification dialogue-act overridesPRE_AGENT_MCPas the final start gate
Recommended step-level strategy
For confirmation-first business flows, the best pipeline behavior is:
Recommended routing behavior
| Situation | What should happen | What should be skipped |
|---|---|---|
| Schema just became complete | POST_SCHEMA_EXTRACTION moves to CONFIRMATION | No MCP yet |
| User AFFIRM in CONFIRMATION | CorrectionStep sets routing_decision and PRE_AGENT_MCP starts MCP | Skip schema extraction; usually skip intent re-resolution |
| User EDIT in CONFIRMATION | CorrectionStep patches the field and re-confirms | Skip full schema extraction when patch is deterministic |
| User reply is ambiguous | Fall back to clarification or a small patch path | Do not blindly rerun the full flow |
Keep control in structured runtime state (inputParams, context, dialogue_act, routing_decision) and keep prompts focused on wording. Use rules and steps for routing, not prompt text for control flow.