Skip to main content
v2

MCP Example 3 - Loan Application Extended

This is the confirmation-first version of the loan flow built around the newer runtime behavior:

  • CorrectionStep handles confirmation affirmations and in-place edits
  • POST_DIALOGUE_ACT can override guarded dialogue-act output before interaction policy runs
  • POST_SCHEMA_EXTRACTION moves the flow into confirmation once required data is complete
  • PRE_AGENT_MCP delays MCP until the user explicitly confirms
  • SET_INPUT_PARAM can mark confirmation runtime flags without extra Java code
  • SET_DIALOGUE_ACT can safely promote an LLM candidate act (for example EDIT) back into the final dialogue_act
  • ConvEngineVerboseAdapter / ce_verbose can 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

Current demo seed gap

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

StatePurposeWhat happens here
IDLELoan intake entryIntent is recognized; rule moves into ELIGIBILITY_GATE.
ELIGIBILITY_GATERequired field collectionSchema extraction collects customerId, requestedAmount, tenureMonths.
CONFIRMATIONUser reviewShow exact collected values; allow AFFIRM or EDIT.
PROCESS_APPLICATIONMCP executionPlanner runs credit -> fraud -> debt -> submit in sequence.
COMPLETEDFinal answerDerived response uses context.mcp.finalAnswer as the primary summary.
Turn 1 - User
Hi
Turn 1 - Assistant
intent: GREETINGstate: IDLE
Hi, how can I help you today?
Turn 2 - User
I need a loan for my customer
Turn 2 - Assistant
intent: LOAN_APPLICATIONstate: ELIGIBILITY_GATE
Please provide customerId, requestedAmount, and tenureMonths.
Turn 3 - User
customer id 1234, 35000, 24 months
Turn 3 - Assistant
intent: LOAN_APPLICATIONstate: CONFIRMATION
Please confirm: customerId 1234, requestedAmount 35000, tenureMonths 24. Proceed?
Turn 4 - User
Ohh wait, I missed one zero. Change amount to 350000.
Turn 4 - Assistant
intent: LOAN_APPLICATIONstate: CONFIRMATION
Updated. Please confirm: customerId 1234, requestedAmount 350000, tenureMonths 24. Proceed?
Turn 5 - User
Looks good, go ahead.
Turn 5 - Internal MCP Loop
intent: LOAN_APPLICATIONstate: PROCESS_APPLICATION
Confirmation accepted. Starting loan processing. PRE_AGENT_MCP moves to PROCESS_APPLICATION. Planner executes credit -> fraud -> debt -> submit.
Turn 5 - Final
intent: LOAN_APPLICATIONstate: COMPLETED
Loan application submitted successfully for customer 1234. Requested amount: 350000, tenure: 24 months. Credit rating passed, fraud check clear, debt profile acceptable. Application ID: APP-90817.

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

PhaseWhen it runsUse it for
POST_SCHEMA_EXTRACTIONImmediately after schema merge and schemaComplete recomputeMove to CONFIRMATION, set confirmation flags, seed lightweight runtime variables.
PRE_AGENT_MCPAt the start of MCP execution, just before planner/tool logicFinal gate for starting MCP, changing state, or skipping MCP entirely.

In this loan flow:

  1. POST_SCHEMA_EXTRACTION sees schemaComplete=true
  2. it sets state=CONFIRMATION
  3. the active ce_prompt_template for CONFIRMATION should use interaction_mode=CONFIRM
  4. optional interaction_contract can allow affirm, edit, and reset
  5. optional POST_DIALOGUE_ACT rule with SET_DIALOGUE_ACT restores guarded LLM EDIT before interaction policy runs
  6. user replies
  7. CorrectionStep interprets the reply from prompt-template interaction metadata
  8. PRE_AGENT_MCP decides 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:

  • DialogueActStep normalizes yes, go ahead, please do it, looks good into AFFIRM
  • CorrectionStep checks 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 as routing_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:

  • yes
  • go ahead
  • confirm

That is fragile and ambiguous.

Use a scoped runtime pattern:

Confirmation interaction pattern

VariableWho sets itWhy it exists
interaction_modece_prompt_templateMarks that this turn is a confirmation checkpoint.
interaction_contractce_prompt_templateDeclares allowed capabilities such as affirm/edit/reset.
routing_decisionCorrectionStepNormalizes the next branch, for example PROCEED_CONFIRMED.
skip_schema_extractionCorrectionStep or later rulePrevents another schema extraction call for confirm-accept turns.
correction_appliedCorrectionStepLets 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_act
  • inputParams.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_MCP completion rule matches only when context.mcp.lifecycle.finished == true and context.mcp.lifecycle.error == false
  • the PROCESS_APPLICATION prompt template uses interaction_mode=PROCESSING
  • the PROCESS_APPLICATION interaction_contract includes retry
  • CorrectionStep detects retry phrases like retry, try again, and again
  • it sets routing_decision=RETRY_IN_PLACE, skip_intent_resolution=true, and skip_schema_extraction=true
  • McpToolStep then 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:

  • customerId
  • requestedAmount
  • tenureMonths

and the engine is already in CONFIRMATION, a reply like:

Looks good, go ahead.

should not trigger a full schema extraction again.

Recommended behavior:

  1. DialogueActStep returns AFFIRM
  2. CorrectionStep sees an active confirmation prompt (interaction_mode=CONFIRM)
  3. it sets routing_decision=PROCEED_CONFIRMED
  4. it also sets skip_schema_extraction=true
  5. SchemaExtractionStep is skipped
  6. PRE_AGENT_MCP sees routing_decision=PROCEED_CONFIRMED and moves to PROCESS_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:

  1. detect dialogue_act=EDIT
  2. inspect existing schema in context
  3. patch only the changed field (requestedAmount)
  4. keep untouched fields (customerId, tenureMonths)
  5. recompute schema completeness
  6. stay in CONFIRMATION
  7. set:
    • correction_applied=true
    • correction_target_field=requestedAmount
    • skip_schema_extraction=true

Then the assistant re-renders the confirmation view with only the changed value updated.

That is exactly why this example uses:

  • CONFIRMATION as a dedicated state
  • CorrectionStep before rework
  • SET_INPUT_PARAM for lightweight runtime flags
  • SET_DIALOGUE_ACT for safe post-classification dialogue-act overrides
  • PRE_AGENT_MCP as the final start gate

For confirmation-first business flows, the best pipeline behavior is:

Recommended routing behavior

SituationWhat should happenWhat should be skipped
Schema just became completePOST_SCHEMA_EXTRACTION moves to CONFIRMATIONNo MCP yet
User AFFIRM in CONFIRMATIONCorrectionStep sets routing_decision and PRE_AGENT_MCP starts MCPSkip schema extraction; usually skip intent re-resolution
User EDIT in CONFIRMATIONCorrectionStep patches the field and re-confirmsSkip full schema extraction when patch is deterministic
User reply is ambiguousFall back to clarification or a small patch pathDo not blindly rerun the full flow
The design principle

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.