Developer Guide
This page is the full implementation starter for consumers building flows on top of ConvEngine.
Pipeline Extension Map
Click each node to inspect the components.
Build order for a new flow
- Define intent/state and response rows in
ce_intentandce_response. - Define schema row (if slot collection needed).
- Define rule transitions by phase (
ce_rule). - Define pending actions in
ce_pending_actionfor explicit AFFIRM/NEGATE confirmation flows. - Configure
convengine.flow.*namespaces (e.g. state graph restrictions, disambiguation limits). - Add tool rows and adapters to the orchestration library if external execution is needed via
McpToolExecutor. - Replay test with expected intent/state/dialogue-act assertions.
Review: convengine.flow.* features
Use your application.yml to tune the pipeline without writing Java extension components.
Flow Features
| Subsystem | Purpose | Example Property |
|---|---|---|
| dialogue-act.* | Detect foundational speech acts (AFFIRM, NEGATE) instead of strict intents. | resolute: REGEX_THEN_LLM |
| query-rewrite.* | Automatically rewrite user input before intent resolution. | enabled: true |
| conversation-history.* | Manage conversation history size and summarization. | max-turns: 10 |
| interaction-policy.* | Map dialogue acts to system actions like EXECUTE_PENDING_ACTION. | execute-pending-on-affirm: true |
| action-lifecycle.* | Automatically expire pending actions after N turns. | ttl-turns: 3 |
| disambiguation.* | Configure thresholds for triggering user clarifications. | max-options: 5 |
| guardrail.* | Set up proactive redaction and fail-closed policies. | approval-gate-fail-closed: true |
| state-graph.* | Enforce strict state transition rules for better predictability. | soft-block-on-violation: false |
Extension points
- CeTask
- McpToolExecutor
- Memory Store
Creating a Pending Action Task
package: com.zapper.convengine.tasks
JAVA
@Component("shippingConfirmationTask")
public class ShippingConfirmationTask implements CeTask {
@Override
public TaskResult execute(EngineSession session, CePendingAction action) {
String trackingId = (String) session.getInputParams().get("trackingId");
// Call downstream API
session.putInputParam("shippingStatus", "DISPATCHED");
return TaskResult.success();
}
}
Tool execution adapter
package: com.zapper.convengine.tools
JAVA
@Component("billingToolAdapter")
public class BillingToolAdapter implements McpToolExecutor {
@Override
public ToolExecutionResult invoke(ToolRequest request, EngineSession session) {
if (request.getToolGroup().equals("BILLING")) {
return ToolExecutionResult.success(Map.of("balance", 0.00));
}
return ToolExecutionResult.skipped();
}
}
Custom Session Snapshotting
package: com.zapper.convengine.stores
JAVA
@Component
public class CustomMemoryStore implements ConversationMemoryStore {
@Override
public String summarize(List<TurnSnapshot> turns) {
// Use LLM to compress 20 turns into a 100 character context injection
return llmClient.summarizeWithLimits(turns, 100);
}
}
Operational safety checklist
- Configure Fallbacks: Configure fallback response rows for
UNKNOWN/ANY. - Phase Targeting: Do not depend on one rule only; split constraints across the actual runtime phases (
POST_AGENT_INTENT,POST_SCHEMA_EXTRACTION,PRE_AGENT_MCP,POST_AGENT_MCP,POST_TOOL_EXECUTION,PRE_RESPONSE_RESOLUTION) so each transition happens at the correct boundary. - Priority Bounds: Verify pending-action catalog priorities to avoid ambiguous execution hooks during interaction policy overlaps.
- Guardrails: Monitor the
ce_auditlog forGUARDRAIL_VIOLATIONto track potential malicious end-user prompt injection. - Strict Bounds: Enable
state-graphvalidation before promoting a new flow to production.
Regression strategy
Use ConversationReplayService to replay scripted turns and assert the expected variables at each turn.
ConversationReplayService assertion
file: src/test/java/com/zapper/RegressionTests.java
JAVA
@Test
public void testShippingFlow() {
ReplayResult finalTurn = replayService.runScript("shipping_confirmation_script.json");
assertEquals("SHIPPING_CONFIRMED", finalTurn.getFinalIntent());
assertEquals("EXECUTE_PENDING_ACTION", finalTurn.getAuditStages().getLastSystemAction());
}