CAT System Reasoning Flow¶
This document describes the reasoning flow and agent architecture used by AnswerUsingCatSystem service.
Overview¶
The CAT System processes user input through a multi-step pipeline that: 1. Normalizes input using ontology synonyms 2. Classifies the input to determine intent 3. Routes to the appropriate handler agent 4. Returns a response with reasoning trail
Default Agents¶
The system uses 10 specialized agents:
| Agent Name | Purpose | When Used |
|---|---|---|
classify_input |
Analyzes user input to determine category and intent | Always (Step 1) |
greeting |
Handles greetings and salutations | Category: greeting |
end_conversation |
Handles conversation endings/goodbyes | Category: end_conversation |
redirect |
Handles redirects to other topics/services | Category: redirect |
onto_answer |
Answers using ontology/structured knowledge | Handler type: onto_answer |
out_of_scope |
Handles queries outside the CAT's domain | Category: out_of_scope |
kb_answer |
Answers using knowledge base retrieval | When KB has relevant content |
mcp_answer |
Answers using MCP (Model Context Protocol) | Reserved for MCP integration |
web_answer |
Answers using web search | When KB unavailable & web enabled |
no_web_answer |
Fallback when no KB and web disabled | When KB unavailable & web disabled |
Reasoning Flow Diagram¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INPUT │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 0: Normalize Input Text │
│ ───────────────────────────── │
│ • Uses OntologyNormalizeParser │
│ • Replaces synonyms with canonical terms │
│ • Example: "auto" → "automobile" if defined in ontology │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 1: Classify User Input │
│ ────────────────────────────── │
│ • Handler: classify_input │
│ • Determines: category, handler_type, matched_module, matched_concept │
│ • Extracts: kb_entities, ontology_answer │
│ │
│ Categories: │
│ ┌──────────────────┬─────────────────────────────────────────────────────┐ │
│ │ greeting │ User is greeting (hi, hello, good morning) │ │
│ │ end_conversation │ User is ending chat (bye, thanks, goodbye) │ │
│ │ redirect │ User wants to change topic or be redirected │ │
│ │ out_of_scope │ Query is outside CAT's knowledge domain │ │
│ │ continue │ Normal query - proceed with handler routing │ │
│ └──────────────────┴─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 2: Extract User Persona │
│ ───────────────────────────── │
│ • Uses PersonaInstructionsBuilder │
│ • Retrieves user-specific context if user_id provided │
│ • Personalizes responses based on user history/preferences │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 3: Route Based on Classification │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ greeting │ │end_conversa │ │ redirect │
│ Handler │ │tion Handler │ │ Handler │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│out_of_scope │ │ continue │ │ │
│ Handler │ │ (route) │ │ │
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ handler_type = │ │ handler_type = │
│ "onto_answer" │ │ other/none │
└────────┬────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ onto_answer │ │ Check Knowledge │
│ Handler │ │ Availability │
└─────────────────┘ └────────┬────────┘
│
┌────────────────────┴────────────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Knowledge │ │ Knowledge │
│ Available │ │ NOT Available │
└────────┬────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ kb_answer │ │ web_enabled? │
│ Handler │ └────────┬────────┘
└─────────────────┘ │
┌────────────────┴────────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ web_answer │ │ no_web_answer │
│ Handler │ │ Handler │
└─────────────────┘ └─────────────────┘
Detailed Step Descriptions¶
Step 0: Input Normalization¶
ontology_parser = self._get_ontology_parser()
normalized_input_text = ontology_parser.normalize_input_text(input_text=input_text)
The ontology parser: - Loads synonym mappings from CAT OS ontology - Replaces user terms with canonical ontology terms - Improves matching accuracy for classification and KB search
Step 1: Classification¶
classify_handler = self._get_handler("classify_input")
classification = classify_handler.analyze(
input_text=input_text,
user_id=user_id,
chat_id=chat_id
)
Classification output structure:
{
"category": "greeting|end_conversation|redirect|out_of_scope|continue",
"reason": "Explanation of classification decision",
"handler_type": "onto_answer|out_of_scope|None",
"matched_module": "Ontology module that matched (if any)",
"matched_concept": "Specific concept matched (if any)",
"kb_entities": ["entity1", "entity2"], # For KB filtering
"ontology_answer": "Direct answer from ontology (if available)"
}
Step 2: Persona Extraction¶
persona_builder = self._get_persona_instructions_builder()
user_persona = persona_builder.get_user_persona(user_id) if user_id else {}
User persona is used to: - Personalize response tone and style - Maintain context across conversations - Apply user-specific preferences
Step 3: Handler Routing¶
Each handler follows a consistent interface:
output, agent_response = handler.handle(
input_text=input_text,
user_id=user_id,
chat_id=chat_id,
user_persona=user_persona,
reasoning=reasoning,
bast_id=bast_id,
**additional_params
)
Knowledge Availability Check¶
When category == "continue" and no specific handler_type:
knowledge_checker = self._get_knowledge_availability_checker()
knowledge_result = knowledge_checker.check_availability(
input_text=input_text,
entities=entities
)
knowledge_available = knowledge_result["available"]
The checker:
1. Gets the default KB name from Knowledge Domains
2. Creates a custom retriever with configured accepted_score
3. Queries the KB with input text and entities
4. Returns whether relevant knowledge was found
Agent Configuration¶
Agents are configured from the Agent Pool:
agent_pool = self._cat_response.get("agent_pool")
config = agent_pool.get("agents", {}).get(agent_name, {})
Default configuration structure:
{
"config": {
"instructions": ["Agent-specific instructions"],
"enable_agentic_memory": False,
"enable_user_memories": False,
"add_history_to_context": True,
"num_history_runs": 3,
"search_knowledge": False,
},
"model_id": "gpt-4o",
"enabled": True
}
Reasoning Trail¶
Each step appends to the reasoning list:
reasoning.append(
f"Step 1: Analyzed user input - Category: {category}, "
f"Reason: {reason} ({step1_stopwatch.duration:.3f}s)"
)
Example reasoning trail:
Step 0: Normalized input text with ontology synonyms (0.015s)
Step 1: Analyzed user input - Category: continue, Reason: General knowledge query (0.523s)
Handler type: None
KB entities: ['insurance', 'policy']
Step 2: Extracted user persona for user_id: user123 (0.045s)
Step 3: Checking knowledge availability (0.234s)
Knowledge available: True, Score: 0.85
Step 4: Using kb_answer handler (1.234s)
Response Structure¶
Final response from process_text:
{
"output": "The response text to the user",
"bast_id": "unique-request-identifier",
"classification": {
"category": "continue",
"reason": "...",
"handler_type": "...",
# ... other classification fields
},
"cat_name": "My CAT",
"cat_prefix": "mycat"
}
Reference Storage¶
For agents that retrieve knowledge (kb_answer, web_answer, no_web_answer):
# Store references for later retrieval
self.store_references(bast_id, references)
# Retrieve references
refs = self.get_references(bast_id)
Configuration Refresh¶
To reload configuration from database:
This: 1. Re-fetches CAT from database 2. Updates ontology provider 3. Rebuilds knowledge config 4. Clears agent and handler caches