# pawan300/enterprise_bot architecture

> Architecture diagram of the GitHub repository pawan300/enterprise_bot, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/pawan300/enterprise_bot
- Repository: https://github.com/pawan300/enterprise_bot

## Overview

#### Purpose and Entry Points
This is a local, enterprise-style multi-agent Q&A prototype for synthetic consumer-goods data. It answers structured KPI questions, document-based questions, web-search questions, and bounded computations, producing grounded citations and debug metadata. Interactive entry points are `scripts/chat_cli.py` and `app/streamlit_app.py`; the latter is an inspection UI rather than a production frontend.

#### Orchestration and Conversation State
`QnaAgent` coordinates each turn: it preserves multi-turn context, resolves follow-ups, performs intent/routing decisions, invokes selected agents, and returns formatted answers plus diagnostics. Conversation state and follow-up generation are separate concerns, enabling UI/CLI clients to remain thin.
Paths: `src/qna_agent/orchestrator/agent.py`, `src/qna_agent/orchestrator/conversation.py`, `src/qna_agent/orchestrator/followups.py`.

#### Deterministic Understanding and Metadata Resolution
Before model-driven decisions, deterministic NLU extracts entities, corrects aliases, interprets temporal language, and detects language. The metadata store supplies KPI/dimension definitions, hierarchy relationships, and document metadata; this supports explicit parent-level fallback (for example, an unavailable sub-region resolving to its parent) and overrides conflicting LLM classifications when entity/KPI resolution is decisive.
Paths: `src/qna_agent/nlu/entities.py`, `src/qna_agent/nlu/temporal.py`, `src/qna_agent/catalog/metadata_store.py`.

#### Intent Routing and Specialized Execution
The router selects up to four specialized agents based on question intent and evidence requirements. Structured queries target SQLite; unstructured queries retrieve from generated Markdown documents; web search uses live search or an offline corpus; coding handles calculations. Multi-evidence “why” questions can run structured and unstructured paths together.
Paths: `src/qna_agent/orchestrator/intent.py`, `src/qna_agent/orchestrator/router.py`, `src/qna_agent/subagents/structured_agent.py`, `src/qna_agent/subagents/unstructured_agent.py`, `src/qna_agent/subagents/websearch_agent.py`, `src/qna_agent/subagents/coding_agent.py`.

#### Evidence Stores and Data Boundary
The system’s business corpus is reproducibly generated as a matched structured/unstructured dataset: SQLite warehouse records, Markdown documents, catalog/alias metadata, and an offline web corpus. The shared generator makes document narratives and warehouse events overlap by construction. Agent boundaries should treat retrieved rows, snippets, search results, and computation outputs as evidence passed upstream rather than direct final answers.
Paths: `data/generate_data.py`, `data/warehouse.db`, `data/documents/`, `data/catalog.json`, `data/websearch_corpus.json`.

#### Synthesis, Validation, and Presentation
The synthesizer receives only gathered evidence, drafts a cited response, then deterministically checks that answer numbers are supported. A failed validation triggers retry and ultimately a guaranteed-correct templated fallback. Formatting adds citations, assumptions/fallback notes, and debug fields such as routed agents, SQL, validation retry, latency, and cost.
Paths: `src/qna_agent/orchestrator/synthesizer.py`, `src/qna_agent/orchestrator/formatting.py`, `src/qna_agent/orchestrator/agent.py`.

#### Runtime, Model, and Security Boundaries
Python 3.11+ runs the application. Ollama hosting local `llama3.1:8b` is the sole LLM dependency, isolated behind one client wrapper; no cloud model/API key is required. SQL generated for the warehouse is constrained by an introspected allow-list, read-only execution, and timeout. Generated computation code is AST-restricted and runs with minimal builtins.
Paths: `src/qna_agent/llm/ollama_client.py`, `src/qna_agent/security/sql_guard.py`, `src/qna_agent/security/sandbox.py`, `requirements.txt`.

Main entry points: [`src/qna_agent/orchestrator/agent.py`](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/agent.py) (Q&A coordinator), [`src/qna_agent/orchestrator/router.py`](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/router.py) (Intent router), [`src/qna_agent/orchestrator/synthesizer.py`](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/synthesizer.py) (Cited synthesis), [`data/generate_data.py`](https://github.com/pawan300/enterprise_bot/blob/main/data/generate_data.py) (Corpus generator)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_clients["Interactive clients"]
  node_cli["Chat CLI<br/>Python entry point<br/>[chat_cli.py]"]
  node_streamlit["Inspection UI<br/>Streamlit entry point<br/>[streamlit_app.py]"]
end

subgraph group_orchestration["Orchestration"]
  node_qna_agent{{"Q&amp;A coordinator<br/>turn orchestrator<br/>[agent.py]"}}
  node_conversation["Conversation state<br/>context manager<br/>[conversation.py]"]
  node_followups["Follow-up resolution<br/>context resolver<br/>[followups.py]"]
  node_nlu["Deterministic NLU<br/>entity and temporal parser<br/>[entities.py]"]
  node_metadata[("Metadata store<br/>KPI and hierarchy catalog<br/>[metadata_store.py]")]
  node_router["Intent router<br/>agent selector<br/>[router.py]"]
  node_synthesizer["Cited synthesis<br/>evidence-only answer writer<br/>[synthesizer.py]"]
  node_formatting["Answer formatting<br/>presentation and diagnostics<br/>[formatting.py]"]
end

subgraph group_execution["Specialized execution"]
  node_structured_agent["Structured agent<br/>SQL evidence retriever"]
  node_unstructured_agent["Document agent<br/>document retriever"]
  node_websearch_agent["Web-search agent<br/>search retriever<br/>[websearch_agent.py]"]
  node_coding_agent["Coding agent<br/>bounded computation<br/>[coding_agent.py]"]
end

subgraph group_data["Generated evidence corpus"]
  node_warehouse[("SQLite warehouse<br/>structured evidence<br/>[warehouse.db]")]
  node_documents["Markdown documents<br/>unstructured evidence"]
  node_web_corpus["Offline web corpus<br/>search evidence"]
  node_generator["Corpus generator<br/>data pipeline<br/>[generate_data.py]"]
end

subgraph group_runtime["Runtime safeguards"]
  node_ollama["Ollama client<br/>local LLM boundary<br/>[ollama_client.py]"]
  node_sql_guard["SQL guard<br/>read-only SQL security<br/>[sql_guard.py]"]
  node_sandbox["Code sandbox<br/>AST-restricted execution<br/>[sandbox.py]"]
end

node_cli -->|"submits turns"| node_qna_agent
node_streamlit -->|"submits turns"| node_qna_agent
node_qna_agent -->|"loads and saves context"| node_conversation
node_qna_agent -->|"resolves references"| node_followups
node_qna_agent -->|"normalizes question"| node_nlu
node_nlu -->|"resolves entities and hierarchy"| node_metadata
node_qna_agent -->|"routes intent"| node_router
node_metadata -.->|"overrides decisive classification"| node_router
node_router -->|"structured intent"| node_structured_agent
node_router -->|"document intent"| node_unstructured_agent
node_router -->|"web intent"| node_websearch_agent
node_router -->|"calculation intent"| node_coding_agent
node_structured_agent -->|"constrains SQL"| node_sql_guard
node_sql_guard -->|"read-only queries"| node_warehouse
node_unstructured_agent -->|"retrieves snippets"| node_documents
node_websearch_agent -->|"offline search"| node_web_corpus
node_coding_agent -->|"executes bounded code"| node_sandbox
node_structured_agent -->|"rows as evidence"| node_synthesizer
node_unstructured_agent -->|"snippets as evidence"| node_synthesizer
node_websearch_agent -->|"results as evidence"| node_synthesizer
node_coding_agent -->|"outputs as evidence"| node_synthesizer
node_synthesizer -->|"drafts cited answer"| node_ollama
node_synthesizer -->|"validated answer or fallback"| node_formatting
node_formatting -->|"formatted response"| node_qna_agent
node_generator -->|"generates records"| node_warehouse
node_generator -->|"generates narratives"| node_documents
node_generator -->|"generates offline corpus"| node_web_corpus

click node_cli "https://github.com/pawan300/enterprise_bot/blob/main/scripts/chat_cli.py"
click node_streamlit "https://github.com/pawan300/enterprise_bot/blob/main/app/streamlit_app.py"
click node_qna_agent "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/agent.py"
click node_conversation "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/conversation.py"
click node_followups "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/followups.py"
click node_nlu "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/nlu/entities.py"
click node_metadata "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/catalog/metadata_store.py"
click node_router "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/router.py"
click node_structured_agent "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/structured_agent.py"
click node_unstructured_agent "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/unstructured_agent.py"
click node_websearch_agent "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/websearch_agent.py"
click node_coding_agent "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/coding_agent.py"
click node_warehouse "https://github.com/pawan300/enterprise_bot/blob/main/data/warehouse.db"
click node_web_corpus "https://github.com/pawan300/enterprise_bot/blob/main/data/websearch_corpus.json"
click node_generator "https://github.com/pawan300/enterprise_bot/blob/main/data/generate_data.py"
click node_synthesizer "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/synthesizer.py"
click node_formatting "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/formatting.py"
click node_ollama "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/llm/ollama_client.py"
click node_sql_guard "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/security/sql_guard.py"
click node_sandbox "https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/security/sandbox.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli,node_streamlit toneBlue
class node_qna_agent,node_conversation,node_followups,node_nlu,node_metadata,node_router,node_synthesizer,node_formatting toneAmber
class node_structured_agent,node_unstructured_agent,node_websearch_agent,node_coding_agent toneMint
class node_warehouse,node_documents,node_web_corpus,node_generator toneRose
class node_ollama,node_sql_guard,node_sandbox toneIndigo
```

## Components

### Interactive clients

- [Chat CLI](https://github.com/pawan300/enterprise_bot/blob/main/scripts/chat_cli.py): Python entry point · `scripts/chat_cli.py`
- [Inspection UI](https://github.com/pawan300/enterprise_bot/blob/main/app/streamlit_app.py): Streamlit entry point · Local UI for inspecting answers and diagnostics. · `app/streamlit_app.py`

### Orchestration

- [Q&A coordinator](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/agent.py): turn orchestrator · Coordinates context, routing, evidence collection, and response delivery. · `src/qna_agent/orchestrator/agent.py`
- [Conversation state](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/conversation.py): context manager · `src/qna_agent/orchestrator/conversation.py`
- [Follow-up resolution](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/followups.py): context resolver · `src/qna_agent/orchestrator/followups.py`
- [Deterministic NLU](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/nlu/entities.py): entity and temporal parser · Extracts entities, aliases, temporal terms, and language before model decisions. · `src/qna_agent/nlu/entities.py`
- [Metadata store](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/catalog/metadata_store.py): KPI and hierarchy catalog · Supports definitions, aliases, document metadata, and parent-level fallback. · `src/qna_agent/catalog/metadata_store.py`
- [Intent router](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/router.py): agent selector · Selects up to four evidence-gathering agents. · `src/qna_agent/orchestrator/router.py`
- [Cited synthesis](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/synthesizer.py): evidence-only answer writer · Drafts answers from gathered evidence and citations. · `src/qna_agent/orchestrator/synthesizer.py`
- [Answer formatting](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/orchestrator/formatting.py): presentation and diagnostics · Adds citations, fallback notes, and debug metadata. · `src/qna_agent/orchestrator/formatting.py`

### Specialized execution

- [Structured agent](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/structured_agent.py): SQL evidence retriever · `src/qna_agent/subagents/structured_agent.py`
- [Document agent](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/unstructured_agent.py): document retriever · `src/qna_agent/subagents/unstructured_agent.py`
- [Web-search agent](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/websearch_agent.py): search retriever · `src/qna_agent/subagents/websearch_agent.py`
- [Coding agent](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/subagents/coding_agent.py): bounded computation · `src/qna_agent/subagents/coding_agent.py`

### Generated evidence corpus

Matched structured and document data are generated together.

- [SQLite warehouse](https://github.com/pawan300/enterprise_bot/blob/main/data/warehouse.db): structured evidence · `data/warehouse.db`
- **Markdown documents**: unstructured evidence
- [Offline web corpus](https://github.com/pawan300/enterprise_bot/blob/main/data/websearch_corpus.json): search evidence · `data/websearch_corpus.json`
- [Corpus generator](https://github.com/pawan300/enterprise_bot/blob/main/data/generate_data.py): data pipeline · Generates overlapping warehouse and document narratives. · `data/generate_data.py`

### Runtime safeguards

- [Ollama client](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/llm/ollama_client.py): local LLM boundary · Isolates the local llama3.1:8b model dependency. · `src/qna_agent/llm/ollama_client.py`
- [SQL guard](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/security/sql_guard.py): read-only SQL security · Allow-lists introspected SQL and enforces timeout. · `src/qna_agent/security/sql_guard.py`
- [Code sandbox](https://github.com/pawan300/enterprise_bot/blob/main/src/qna_agent/security/sandbox.py): AST-restricted execution · Runs generated computations with minimal builtins. · `src/qna_agent/security/sandbox.py`

## Connections

- Chat CLI → Q&A coordinator: submits turns
- Inspection UI → Q&A coordinator: submits turns
- Q&A coordinator → Conversation state: loads and saves context
- Q&A coordinator → Follow-up resolution: resolves references
- Q&A coordinator → Deterministic NLU: normalizes question
- Deterministic NLU → Metadata store: resolves entities and hierarchy
- Q&A coordinator → Intent router: routes intent
- Metadata store → Intent router: overrides decisive classification
- Intent router → Structured agent: structured intent
- Intent router → Document agent: document intent
- Intent router → Web-search agent: web intent
- Intent router → Coding agent: calculation intent
- Structured agent → SQL guard: constrains SQL
- SQL guard → SQLite warehouse: read-only queries
- Document agent → Markdown documents: retrieves snippets
- Web-search agent → Offline web corpus: offline search
- Coding agent → Code sandbox: executes bounded code
- Structured agent → Cited synthesis: rows as evidence
- Document agent → Cited synthesis: snippets as evidence
- Web-search agent → Cited synthesis: results as evidence
- Coding agent → Cited synthesis: outputs as evidence
- Cited synthesis → Ollama client: drafts cited answer
- Cited synthesis → Answer formatting: validated answer or fallback
- Answer formatting → Q&A coordinator: formatted response
- Corpus generator → SQLite warehouse: generates records
- Corpus generator → Markdown documents: generates narratives
- Corpus generator → Offline web corpus: generates offline corpus
