Configuration Deep Guide
Table mapping in application.yml (ConvEngine + CCF Core)
Use this when your physical table names differ from defaults. ConvEngine reads convengine.tables.*; CCF Core reads ccf.core.tables.*.
ccf:
core:
tables:
PAGE_COMMON_QUERY: ZP_PAGE_COMMON_QUERY
SECTION_INFO: ZP_SECTION_INFO
CONTAINER_INFO: ZP_CONTAINER_INFO
CONTAINER_FIELD_INFO: ZP_CONTAINER_FIELD_INFO
CONTAINER_QUERY_INFO: ZP_CONTAINER_QUERY_INFO
convengine:
tables:
AUDIT: CE_AUDIT
CONFIG: CE_CONFIG
CONTAINER_CONFIG: CE_CONTAINER_CONFIG
CONVERSATION: CE_CONVERSATION
INTENT: CE_INTENT
INTENT_CLASSIFIER: CE_INTENT_CLASSIFIER
LLM_CALL_LOG: CE_LLM_CALL_LOG
MCP_DB_TOOL: CE_MCP_DB_TOOL
MCP_TOOL: CE_MCP_TOOL
OUTPUT_SCHEMA: CE_OUTPUT_SCHEMA
POLICY: CE_POLICY
PROMPT_TEMPLATE: CE_PROMPT_TEMPLATE
RESPONSE: CE_RESPONSE
RULE: CE_RULE
If you override table names, keep mappings consistent across environments and apply the same naming strategy in JPA config.
ConvEngine does not ship default application.yml values; consumers must provide convengine.* properties.
Complete application.yml reference (demo + full ConvEngine options)
This is a complete starter reference combining convengine-demo style settings and all configurable convengine.* properties currently present in the framework.
server:
port: 8080
spring:
application:
name: convengine
datasource:
url: jdbc:postgresql://localhost:5432/convengine
username: convengine_user
password: convengine_pwd
driver-class-name: org.postgresql.Driver
jpa:
open-in-view: false
hibernate:
ddl-auto: none
naming:
# Use the physical strategy your app needs (demo uses CCF strategy)
physical-strategy: com.github.salilvnair.ccf.config.hibernate.CcfPhysicalNamingStrategy
show-sql: true
properties:
hibernate:
format_sql: true
jdbc:
lob:
non_contextual_creation: true
logging:
level:
root: INFO
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
convengine:
# Demo app-only block (optional, not framework-required)
demo:
stream-mode: SSE # SSE | STOMP | BOTH
step-hook:
enabled: true
# Framework flags
experimental:
enabled: false
# Dynamic table mapping for CE_* entities
tables:
AUDIT: CE_AUDIT
CONFIG: CE_CONFIG
CONTAINER_CONFIG: CE_CONTAINER_CONFIG
CONVERSATION: CE_CONVERSATION
INTENT: CE_INTENT
INTENT_CLASSIFIER: CE_INTENT_CLASSIFIER
LLM_CALL_LOG: CE_LLM_CALL_LOG
MCP_DB_TOOL: CE_MCP_DB_TOOL
MCP_TOOL: CE_MCP_TOOL
OUTPUT_SCHEMA: CE_OUTPUT_SCHEMA
POLICY: CE_POLICY
PROMPT_TEMPLATE: CE_PROMPT_TEMPLATE
RESPONSE: CE_RESPONSE
RULE: CE_RULE
transport:
sse:
enabled: true
emitter-timeout-ms: 1800000
stomp:
enabled: false
endpoint: /ws-convengine
app-destination-prefix: /app
topic-prefix: /topic
audit-destination-base: /topic/convengine/audit
allowed-origin-pattern: "*"
sock-js: true
broker:
mode: SIMPLE # SIMPLE | RELAY
relay-destination-prefixes: /topic,/queue
relay-host: localhost
relay-port: 61613
client-login: ""
client-passcode: ""
system-login: ""
system-passcode: ""
virtual-host: ""
system-heartbeat-send-interval-ms: 10000
system-heartbeat-receive-interval-ms: 10000
audit:
enabled: true
persist-meta: true
level: ALL # ALL | STANDARD | ERROR_ONLY | NONE
include-stages: []
exclude-stages: []
persistence:
mode: IMMEDIATE # IMMEDIATE | DEFERRED_BULK
jdbc-batch-size: 200
max-buffered-events: 5000
flush-stages: ENGINE_KNOWN_FAILURE,ENGINE_UNKNOWN_FAILURE
final-step-names: PipelineEndGuardStep
flush-on-stop-outcome: true
dispatch:
async-enabled: false
worker-threads: 2
queue-capacity: 2000
rejection-policy: CALLER_RUNS # CALLER_RUNS | DROP_NEWEST | DROP_OLDEST | ABORT
keep-alive-seconds: 60
rate-limit:
enabled: false
max-events: 200
window-ms: 1000
per-conversation: true
per-stage: true
max-tracked-buckets: 20000
# Example consumer-specific LLM block (optional, used by demo-style adapters)
# llm:
# provider: openai
# temperature: 0.3
# openai:
# api-key: ${OPENAI_API_KEY}
# model: gpt-4.1
# base-url: https://api.openai.com
# lmstudio:
# api-key: ${LMSTUDIO_API_KEY}
# model: openai/gpt-oss-20b
# base-url: http://localhost:1234
ccf:
core:
tables:
PAGE_COMMON_QUERY: ZP_PAGE_COMMON_QUERY
SECTION_INFO: ZP_SECTION_INFO
CONTAINER_INFO: ZP_CONTAINER_INFO
CONTAINER_FIELD_INFO: ZP_CONTAINER_FIELD_INFO
CONTAINER_QUERY_INFO: ZP_CONTAINER_QUERY_INFO
@EnableConvEngine(stream = true|false) is annotation-driven. It is not a YAML property; keep transport flags aligned with the annotation mode.
ce_prompt_template in detail
ce_prompt_template holds reusable prompt text for both schema extraction and derived response generation.
Use response_type to route templates:
SCHEMA_JSONfor schema extraction promptsTEXTfor derived text response promptsJSONfor derived json response prompts
-- Schema extraction template
INSERT INTO ce_prompt_template
(intent_code, state_code, response_type, system_prompt, user_prompt, enabled)
VALUES
('DISCONNECT_ELECTRICITY', 'COLLECTING', 'SCHEMA_JSON',
'Extract required fields strictly as JSON. No commentary.',
'User: {{user_input}}
Context: {{context}}
Schema: {{schema}}',
true);
-- Derived text response template
INSERT INTO ce_prompt_template
(intent_code, state_code, response_type, system_prompt, user_prompt, enabled)
VALUES
('REQUEST_TRACKER', 'IDLE', 'TEXT',
'You are a concise status assistant. Keep response under 3 lines.',
'User: {{user_input}}
Context: {{context}}
Session: {{session}}',
true);
ce_config in detail
ce_config stores runtime tunables keyed by component class.
Common keys:
AgentIntentResolver.MIN_CONFIDENCEAgentIntentResolver.COLLISION_GAP_THRESHOLDAgentIntentResolver.SYSTEM_PROMPTAgentIntentResolver.USER_PROMPTMcpPlanner.SYSTEM_PROMPTMcpPlanner.USER_PROMPTResetResolvedIntentStep.RESET_INTENT_CODESIntentResolutionStep.STICKY_INTENT
INSERT INTO ce_config (config_type, config_key, config_value, enabled) VALUES
('AgentIntentResolver', 'MIN_CONFIDENCE', '0.60', true),
('AgentIntentResolver', 'COLLISION_GAP_THRESHOLD', '0.15', true),
('ResetResolvedIntentStep', 'RESET_INTENT_CODES', 'RESET_SESSION,START_OVER', true),
('IntentResolutionStep', 'STICKY_INTENT', 'true', true),
('McpPlanner', 'SYSTEM_PROMPT', 'You are an MCP planner. Prefer safe calls and minimal arguments.', true),
('McpPlanner', 'USER_PROMPT', 'User: {{user_input}}
Tools: {{mcp_tools}}
Context: {{context}}', true);
Implemented type/action values
| Field | Allowed values | Notes |
|---|---|---|
| ce_response.response_type | EXACT, DERIVED | EXACT bypasses LLM generation |
| ce_response.output_format | TEXT, JSON | Used by output format resolver |
| ce_rule.rule_type | EXACT, REGEX, JSON_PATH | Must match installed rule type resolvers |
| ce_rule.phase | PIPELINE_RULES, AGENT_POST_INTENT | Controls whether rule runs in RulesStep or AgentIntentResolver post-intent pass |
| ce_rule.state_code | NULL, ANY, specific state code | NULL/ANY apply across states; specific value scopes execution to that state |
| ce_rule.action | SET_INTENT, SET_STATE, SET_JSON, GET_CONTEXT, GET_SCHEMA_JSON, GET_SESSION, SET_TASK | Must match installed action resolvers |
ce_output_schema in detail
ce_output_schema defines extraction contract per intent/state. SchemaExtractionStep uses this JSON schema to detect missing fields and drive clarification flow.
-- Core columns (simplified)
CREATE TABLE ce_output_schema (
schema_id BIGSERIAL PRIMARY KEY,
intent_code TEXT NOT NULL,
state_code TEXT NOT NULL,
schema_name TEXT,
schema_description TEXT,
json_schema JSONB NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
INSERT INTO ce_output_schema
(intent_code, state_code, schema_name, schema_description, json_schema, enabled)
VALUES
(
'DISCONNECT_ELECTRICITY',
'COLLECTING',
'disconnect_request',
'Required data to process electricity disconnect request.',
'{
"type":"object",
"required":["accountNumber","reason"],
"properties":{
"accountNumber":{"type":"string"},
"reason":{"type":"string","enum":["MOVE_OUT","TEMP_CLOSE","PERMANENT_CLOSE"]},
"requestedDate":{"type":"string","format":"date"}
}
}'::jsonb,
true
);
ce_response in detail
ce_response maps resolved intent/state to response strategy.
EXACT: static response body from DB.DERIVED: runtime generated response (LLM), optionally usingce_prompt_template.
CREATE TABLE ce_response (
response_id BIGSERIAL PRIMARY KEY,
intent_code TEXT NOT NULL,
state_code TEXT NOT NULL,
response_type TEXT NOT NULL, -- EXACT | DERIVED
output_format TEXT NOT NULL, -- TEXT | JSON
response_text TEXT,
response_json JSONB,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- EXACT TEXT response
INSERT INTO ce_response
(intent_code, state_code, response_type, output_format, response_text, enabled)
VALUES
('FAQ', 'IDLE', 'EXACT', 'TEXT', 'Yes, you can move your connection using Zapper app.', true);
-- DERIVED JSON response
INSERT INTO ce_response
(intent_code, state_code, response_type, output_format, response_json, enabled)
VALUES
('REQUEST_TRACKER', 'IDLE', 'DERIVED', 'JSON', '{"template":"status-card"}'::jsonb, true);
ce_rule in detail
ce_rule is the conditional transition/action layer executed in RulesStep.
rule_type:EXACT,REGEX,JSON_PATHphase:PIPELINE_RULES,AGENT_POST_INTENTstate_code:NULL(all states),ANY(all states), or specific state codeaction:SET_INTENT,SET_STATE,SET_JSON,GET_CONTEXT,GET_SCHEMA_JSON,GET_SESSION,SET_TASK
CREATE TABLE ce_rule (
rule_id BIGSERIAL PRIMARY KEY,
phase TEXT NOT NULL DEFAULT 'PIPELINE_RULES',
intent_code TEXT NULL,
state_code TEXT NULL,
rule_type TEXT NOT NULL,
match_pattern TEXT NOT NULL,
action TEXT NOT NULL,
action_value TEXT NULL,
priority INT NOT NULL DEFAULT 100,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
description TEXT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- If user says reset keywords, set reset intent
INSERT INTO ce_rule
(phase, intent_code, state_code, rule_type, match_pattern, action, action_value, priority, enabled, description)
VALUES
('PIPELINE_RULES', 'FAQ', 'ANY', 'REGEX', '(?i)^(reset|restart)$', 'SET_INTENT', 'RESET_SESSION', 10, true, 'Reset intent switch');
-- Agent post-intent bootstrap
INSERT INTO ce_rule
(phase, intent_code, state_code, rule_type, match_pattern, action, action_value, priority, enabled, description)
VALUES
('AGENT_POST_INTENT', 'MAPPING_STUDIO', 'ANY', 'JSON_PATH',
'$[?(@.intent == ''MAPPING_STUDIO'' && (@.state == ''UNKNOWN'' || @.state == ''IDLE''))]',
'SET_STATE', 'COLLECT_INPUTS', 5, true, 'Bootstrap mapping state during post-intent pass');
ce_rule.phase execution semantics
Use phase to control where a rule executes.
Rule Phase Execution Matrix
| phase | Executed by | When it runs | Typical usage |
|---|---|---|---|
| PIPELINE_RULES | RulesStep | Normal pipeline pass after schema/auto-advance | Business transitions, context actions, SET_TASK in standard flow |
| AGENT_POST_INTENT | AgentIntentResolver post-intent pass | Immediately after agent accepts intent | Bootstrap state from UNKNOWN/IDLE based on resolved intent |
ce_rule.state_code execution semantics
Use state_code to reduce unnecessary rule evaluations:
Rule State Scope Matrix
| state_code value | Runtime behavior |
|---|---|
| NULL | Rule is eligible in all states |
| ANY | Rule is eligible in all states |
| Specific state (for example COLLECT_INPUTS) | Rule is eligible only when session.state matches (case-insensitive) |
INSERT INTO ce_rule
(phase, intent_code, state_code, rule_type, match_pattern, action, action_value, priority, enabled, description)
VALUES
('AGENT_POST_INTENT', 'MAPPING_STUDIO', 'ANY', 'JSON_PATH',
'$[?(@.intent == ''MAPPING_STUDIO'' && (@.state == ''UNKNOWN'' || @.state == ''IDLE''))]',
'SET_STATE', 'COLLECT_INPUTS', 5, true,
'Bootstrap Mapping Studio state right after agent intent resolution');
EngineSession/inputParams include phase metadata:
postIntentRule/post_intent_rulerule_phaserule_execution_sourcerule_execution_origin
Prompt variable guidance
Common variables used in templates:
{{user_input}}{{context}}{{session}}{{schema}}{{conversation_history}}- schema helpers:
{{missing_fields}},{{missing_field_options}},{{schema_description}}
Prompt template extra now includes all keys present in inputParams, including runtime/system-derived keys written through session.putInputParam(...). Keep key naming and values controlled in consumer task/rule code.
Runtime transport/audit properties
convengine:
transport:
stomp:
enabled: true
broker:
mode: SIMPLE # SIMPLE | RELAY
relay-destination-prefixes: /topic,/queue
relay-host: localhost
relay-port: 61613
client-login: ""
client-passcode: ""
system-login: ""
system-passcode: ""
virtual-host: ""
system-heartbeat-send-interval-ms: 10000
system-heartbeat-receive-interval-ms: 10000
audit:
enabled: true
level: ALL # ALL | STANDARD | ERROR_ONLY | NONE
include-stages: []
exclude-stages: []
persistence:
mode: IMMEDIATE # IMMEDIATE | DEFERRED_BULK
jdbc-batch-size: 200
max-buffered-events: 5000
flush-stages: ENGINE_KNOWN_FAILURE,ENGINE_UNKNOWN_FAILURE
final-step-names: PipelineEndGuardStep
flush-on-stop-outcome: true
dispatch:
async-enabled: false
worker-threads: 2
queue-capacity: 2000
rejection-policy: CALLER_RUNS # CALLER_RUNS | DROP_NEWEST | DROP_OLDEST | ABORT
keep-alive-seconds: 60
rate-limit:
enabled: false
max-events: 200
window-ms: 1000
per-conversation: true
per-stage: true
max-tracked-buckets: 20000
@EnableConvEngine(stream = true)
@EnableConvEngineAsyncAuditDispatch
@EnableConvEngineStompBrokerRelay
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
New 1.0.8+ runtime controls explained
- Async audit dispatch:
- Moves transport fan-out off request thread when enabled.
- Configure with
convengine.audit.dispatch.*or@EnableConvEngineAsyncAuditDispatch.
- Backpressure policy:
- Queue capacity + rejection policy control behavior under burst.
CALLER_RUNSis safest default;DROP_*favors latency;ABORTis strict.
- Stage-level audit controls:
level,include-stages,exclude-stages, andrate-limitreduce noisy audit traffic.
- Deferred bulk persistence:
convengine.audit.persistence.mode=DEFERRED_BULKbuffers events and writes batch inserts.- Flushes on terminal step/error (configurable), plus request-end safety flush.
- STOMP broker mode:
SIMPLE(default): in-memory broker.RELAY: external STOMP broker (RabbitMQ/other relay supporting STOMP).
RabbitMQ relay example
convengine:
transport:
stomp:
enabled: true
endpoint: /ws-convengine
app-destination-prefix: /app
topic-prefix: /topic
audit-destination-base: /topic/convengine/audit
broker:
mode: RELAY
relay-destination-prefixes: /topic,/queue
relay-host: localhost
relay-port: 61613
client-login: guest
client-passcode: guest
system-login: guest
system-passcode: guest
virtual-host: /
system-heartbeat-send-interval-ms: 10000
system-heartbeat-receive-interval-ms: 10000
Redis example (via STOMP gateway/bridge)
ConvEngine STOMP relay requires a STOMP-compatible broker endpoint. Redis alone is not a native STOMP broker; use a STOMP gateway/bridge in front of Redis.
convengine:
transport:
stomp:
enabled: true
broker:
mode: RELAY
relay-destination-prefixes: /topic,/queue
relay-host: redis-stomp-bridge.local
relay-port: 61613
client-login: ""
client-passcode: ""
system-login: ""
system-passcode: ""
virtual-host: ""