Live App →

Zen — Financial AI Chat

Zen is Sentinel’s conversational AI engine built for wealth management professionals. Ask questions about markets, portfolios, regulations, and financial products. Upload documents for contextual Q&A powered by RAG (Retrieval-Augmented Generation). Toggle web search for real-time market data, stock prices, and mutual fund NAVs.

Zen uses a non-streaming synchronous architecture — each message gets a complete response in a single API call. No SSE, no WebSockets, no partial rendering. The backend processes the query through intelligent agents, applies guardrail checks, and returns the full response with metadata.


Chat Flow

sequenceDiagram
    participant U as User
    participant FE as Frontend
    participant BFF as Studio BFF
    participant ZEN as Zen Backend

    U->>FE: Click "Start New Chat"
    FE->>BFF: POST /api/v1/zen/chat/
    BFF-->>FE: Session UUID
    FE->>FE: Navigate to /zen/chat/{uuid}

    U->>FE: Type message + send
    FE->>BFF: POST /api/v1/zen/chat/invoke (FormData)
    Note over FE,BFF: session_id, query, web_search,<br/>agent_id, skip_guardrail
    BFF->>ZEN: Forward to Zen Backend
    ZEN-->>BFF: {response, meta, guardrail}
    BFF-->>FE: ResponseEnvelope
    FE->>FE: Render markdown response

Step-by-step:

  1. Create Session — User clicks “Start New Chat” in the sidebar. The frontend sends POST /api/v1/zen/chat/ to create a new session. The backend returns a UUID.
  2. Navigate — The frontend navigates to /zen/chat/{uuid}. The chat interface loads with an empty conversation.
  3. Send Message — User types a question and hits send. The frontend packages the message as FormData and sends it to the invoke endpoint.
  4. Process — The Studio BFF forwards the request to the Zen backend. The backend routes the query through the appropriate agent, optionally performs web search, applies guardrails, and generates a response.
  5. Render — The frontend receives the complete response and renders it as financial-aware markdown with tables, currency formatting, and color-coded metrics.

Key Features

Toggle web search directly in the chat input area. When enabled, the AI queries the web for real-time information before generating a response.

What it provides:

  • Live stock prices and index levels
  • Latest mutual fund NAVs and returns
  • Recent market news and regulatory updates
  • Fund performance comparisons with current data

How it works:

  • The web_search field in the invoke request is a string: "True" or "False"
  • The response meta.web_search field indicates whether web search was actually used
  • Web search adds latency (typically 2-5 seconds) but provides current data instead of training cutoff data

When to use it:

  • Current prices, NAVs, or index levels
  • Recent regulatory changes or SEBI circulars
  • Fund performance over specific recent periods
  • Any question where “as of today” matters

Nexus Document Integration

Zen sessions can now receive documents sourced directly from the Nexus pipeline. When a Nexus-processed financial document is attached to a session, the chat page shows a NexusProcessingIndicator — a live status banner that tracks the document through the 10-stage pipeline.

How it works:

  1. A Nexus document is linked to the session (via SessionDocument.source = 'nexus').
  2. The frontend polls GET /zen/chat/{sessionId}/documents/{docId}/status every few seconds.
  3. The indicator shows the current pipeline stage (current_stage) and percentage complete (progress_pct).
  4. Once status reaches 'completed', the indicator dismisses and the document is available for RAG queries.

The status endpoint is polled with suppressAuthEvent: true, so 401 responses from background polling do not trigger the global session-expired modal.

Session document fields (SessionDocument):

Field Description
doc_id Unique document identifier
filename Original file name
source 'upload', 'nexus', or 's3_url'
status Current processing state
nexus_process_id Nexus V2 process ID for progress polling
nexus_job_id Nexus job ID

RAG Document Upload

Upload documents directly into a chat session for contextual Q&A. The uploaded files are processed and indexed, allowing the AI to answer questions specifically about the document content.

Supported flow:

  1. Click the attachment icon in the chat input
  2. Select PDF or document files
  3. Files are uploaded via POST /api/v1/zen/uploads/
  4. Ask questions about the uploaded content
  5. The AI retrieves relevant sections from the document to ground its answers

Use cases:

  • Upload a CAS and ask “What is my total equity exposure?”
  • Upload a scheme document and ask “What are the exit load conditions?”
  • Upload a regulatory circular and ask “What are the key compliance changes?”

Guardrails

Every response passes through a safety guardrail system. Guardrails ensure responses stay within appropriate boundaries for financial advice.

Response behavior:

  • guardrail: null — No guardrail was triggered. The response is clean.
  • guardrail: { passed: true, reason: null } — Guardrail evaluated and passed.
  • guardrail: { passed: false, reason: "..." } — Guardrail triggered. The reason explains why the response was flagged. The UI may display a warning alongside the response.

The skip_guardrail field in the invoke request is always set to "false" in production. It exists for development testing only.

Agent Invocation

The Zen backend uses specialized agents to handle different types of queries. The meta.agents_invoked array in the response reveals which agents processed the query.

Agents are selected automatically based on query intent. The default agent handles general financial questions. Specialized agents handle portfolio analysis, regulatory queries, and market data requests.

Default agent_id: 6989c8987e0f5c816015fd18

The agent ID is sent with every invoke request. The backend may invoke additional agents internally based on the query content.

Agent Invocation Flow

The following diagram illustrates how the Zen backend routes an incoming query through its agent system. The default agent acts as the entry point and may delegate to specialized agents depending on query intent.

flowchart TD
    Q["User Query"]:::primary --> GR{"Guardrail<br/>Check"}:::warning
    GR -->|Blocked| WARN["Return guardrail<br/>warning"]:::danger
    GR -->|Passed| ROUTER["Agent Router"]:::secondary

    ROUTER --> DEFAULT["Default Agent<br/>General Q&A"]:::highlight
    ROUTER --> PORTFOLIO["Portfolio Agent<br/>Holdings analysis"]:::highlight
    ROUTER --> REGULATORY["Regulatory Agent<br/>SEBI & compliance"]:::highlight
    ROUTER --> MARKET["Market Agent<br/>Prices & NAVs"]:::highlight

    DEFAULT --> WS{"Web Search<br/>enabled?"}:::warning
    PORTFOLIO --> WS
    REGULATORY --> WS
    MARKET --> WS

    WS -->|Yes| SEARCH["Web Search<br/>Fetch live data"]:::neutral
    WS -->|No| RAG{"Documents<br/>uploaded?"}:::warning
    SEARCH --> GEN["Generate Response"]:::secondary
    RAG -->|Yes| RETRIEVE["RAG Retrieval<br/>Doc chunks"]:::neutral
    RAG -->|No| GEN
    RETRIEVE --> GEN

    GEN --> RESP["Return response<br/>+ meta + guardrail"]:::success

    classDef primary fill:#dbeafe,stroke:#3b82f6,color:#1e293b
    classDef secondary fill:#e0e7ff,stroke:#6366f1,color:#1e293b
    classDef success fill:#d1fae5,stroke:#10b981,color:#1e293b
    classDef warning fill:#fef3c7,stroke:#f59e0b,color:#1e293b
    classDef danger fill:#fee2e2,stroke:#ef4444,color:#1e293b
    classDef neutral fill:#f1f5f9,stroke:#64748b,color:#1e293b
    classDef highlight fill:#fae8ff,stroke:#a855f7,color:#1e293b
    classDef dark fill:#1e293b,stroke:#334155,color:#f8fafc

Web Search vs RAG Query Paths

When a user sends a message, the query follows one of two enrichment paths depending on the toggle states — web search for live external data, or RAG retrieval for uploaded document context. These paths are mutually exclusive in practice.

flowchart LR
    subgraph Input
        MSG["User Message"]:::primary
    end

    MSG --> CHECK{"web_search<br/>= true?"}:::warning

    CHECK -->|Yes| WEB_PATH
    CHECK -->|No| DOC_CHECK{"Documents<br/>in session?"}:::warning

    subgraph WEB_PATH["Web Search Path"]
        W1["Query search engine<br/>for live data"]:::danger --> W2["Inject results<br/>into context"]:::danger
    end

    DOC_CHECK -->|Yes| RAG_PATH
    DOC_CHECK -->|No| DIRECT["Direct LLM query<br/>training data only"]:::neutral

    subgraph RAG_PATH["RAG Path"]
        R1["Embed query &<br/>vector search"]:::highlight --> R2["Retrieve top-k<br/>doc chunks"]:::highlight --> R3["Inject chunks<br/>into context"]:::highlight
    end

    WEB_PATH --> LLM["LLM generates<br/>grounded response"]:::success
    RAG_PATH --> LLM
    DIRECT --> LLM

    classDef primary fill:#dbeafe,stroke:#3b82f6,color:#1e293b
    classDef secondary fill:#e0e7ff,stroke:#6366f1,color:#1e293b
    classDef success fill:#d1fae5,stroke:#10b981,color:#1e293b
    classDef warning fill:#fef3c7,stroke:#f59e0b,color:#1e293b
    classDef danger fill:#fee2e2,stroke:#ef4444,color:#1e293b
    classDef neutral fill:#f1f5f9,stroke:#64748b,color:#1e293b
    classDef highlight fill:#fae8ff,stroke:#a855f7,color:#1e293b
    classDef dark fill:#1e293b,stroke:#334155,color:#f8fafc

The Web Search Path fetches real-time data from the internet (stock prices, NAVs, news). The RAG Path retrieves relevant sections from documents the user uploaded into the session. If neither is active, the LLM answers from its training knowledge alone.


Suggested Query Categories

Market Intelligence (web_search = true)

These queries benefit from real-time web data:

  • “What are the latest NAV updates for SBI Bluechip Fund?”
  • “Compare Nifty 50 vs Sensex performance this year”
  • “What is the current yield on 10-year government bonds?”
  • “Show me the top performing large cap mutual funds this quarter”
  • “What did SEBI announce about mutual fund fee structures recently?”
  • “What is the current AUM of HDFC AMC?”

Portfolio Analysis (web_search = false)

These queries work best with uploaded documents or prior context:

  • “Analyze my portfolio’s asset allocation”
  • “What is the total invested value across all holdings?”
  • “Which funds in my portfolio have the highest expense ratio?”
  • “Show me all holdings with negative returns”
  • “What percentage of my portfolio is in mid-cap funds?”
  • “Summarize the capital gains from this statement”

Regulatory and Product Knowledge

  • “Explain the difference between direct and regular mutual fund plans”
  • “What are the LTCG tax rules for equity mutual funds?”
  • “How does SWP (Systematic Withdrawal Plan) work?”
  • “What is the lock-in period for ELSS funds?”

Session Management

Chat sessions are listed in the left sidebar, organized by date groups.

Session Lifecycle

A chat session moves through several states from creation to deletion. The diagram below captures the full lifecycle including file uploads, auto-renaming, and termination.

stateDiagram-v2
    [*] --> Created: POST /zen/chat/
    Created --> Active: First message sent
    Active --> Active: More messages
    Active --> WithDocs: File uploaded
    WithDocs --> Active: Query with RAG context
    Active --> Renamed: Auto-title after first response
    Renamed --> Active: Continue chatting
    Active --> Deleted: User deletes
    Deleted --> [*]

Sessions are auto-titled after the first assistant response based on the conversation content. The user can also manually rename a session at any time by double-clicking the title in the sidebar.

Date Grouping

Sessions are grouped into time-based categories:

Group Rule
Today Sessions created or last active today
Yesterday Sessions from yesterday
This Week Sessions from the current week (excluding today/yesterday)
Earlier All older sessions

Session Actions

  • Rename — Double-click the session title in the sidebar to enter edit mode. Type a new name and press Enter to save, or Escape to cancel.
  • Delete — Click the delete icon on a session. A confirmation dialog appears. Deletion is permanent and removes all messages in the session.
  • Switch — Click any session in the sidebar to load its conversation history.

Session Persistence

All messages within a session are persisted on the backend. Navigating away and returning loads the full conversation history. Session history is fetched via GET /api/v1/zen/chat/{session_id}/history.


Chat Message Rendering

Zen responses are rendered with financial-aware markdown processing optimized for wealth management content.

Currency Formatting

Monetary values are detected and formatted with proper Indian numbering (lakhs, crores) or international formatting based on context:

  • Rs. 1,23,456.78 (Indian format)
  • $1,234,567.89 (International format)

Percentage Coloring

Return percentages are color-coded for instant visual feedback:

  • Green — Positive returns (gains)
  • Red — Negative returns (losses)
  • Neutral — Zero or informational percentages

Table Rendering

Financial tables are rendered with:

  • Right-aligned numeric columns
  • Proper decimal alignment for currency and percentage values
  • Sortable headers where applicable
  • Responsive horizontal scrolling for wide tables

Callout Detection

Special response sections are detected and rendered as styled callouts:

  • Warning — Risk disclaimers, compliance notes
  • Info — Educational explanations, definitions
  • Tip — Actionable suggestions, best practices

API Contract

Create Session

POST /api/v1/zen/chat/

Response:

{
  "status": "success",
  "data": {
    "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Invoke (Send Message)

POST /api/v1/zen/chat/invoke
Content-Type: multipart/form-data

FormData Fields:

Field Type Required Description
session_id string Yes UUID of the chat session
query string Yes The user’s message text
skip_guardrail string Yes Always "false" in production
web_search string Yes "true" or "false" — whether to search the web
agent_id string Yes Agent identifier. Default: "6989c8987e0f5c816015fd18"

Response:

{
  "status": "success",
  "data": {
    "message_id": "msg-uuid-user",
    "response_message_id": "msg-uuid-assistant",
    "response": "Markdown formatted response text...",
    "meta": {
      "web_search": "True",
      "agents_invoked": ["agent-name"],
      "processing_time_ms": 3200
    },
    "guardrail": null,
    "error": null
  }
}

Fetch Session History

GET /api/v1/zen/chat/{session_id}/history

Returns all messages in the session, ordered chronologically. Each message includes role (user, assistant, or system), content, timestamp, and metadata.

System messages: The backend may inject role: 'system' messages for pipeline status notifications (e.g., when a Nexus document finishes processing). These are rendered as informational banners rather than chat bubbles.

Upload Document

POST /api/v1/zen/uploads/
Content-Type: multipart/form-data

Upload files for RAG-powered contextual Q&A within the session.

List Sessions

GET /api/v1/zen/chat/

Returns all sessions for the authenticated user, ordered by last activity. Used to populate the sidebar.

Delete Session

DELETE /api/v1/zen/chat/{session_id}

Permanently removes the session and all its messages. Supports keepalive: true to ensure the request completes even when called during page navigation (e.g., on tab close).


Frontend Routes

Route Description
/zen Landing page. Shows the session sidebar and a prompt to start a new chat or select an existing session.
/zen/chat/[sessionId] Active chat interface for a specific session. Displays message history, input bar with web search toggle, and file upload.

Architecture Notes

  • Non-streaming — Zen uses synchronous request-response. The frontend shows a loading indicator while waiting for the complete response. No partial message streaming.
  • BFF Proxy — All Zen API calls route through the Studio BFF via a wildcard proxy at /api/v1/zen/*. Unlike Nexus (which has 32 explicitly defined routes), Zen uses a single wildcard that forwards all paths to the Zen backend.
  • FormData — The invoke endpoint uses multipart/form-data rather than JSON. All fields are strings, including booleans ("true" / "false").
  • ResponseEnvelope — The Studio API client automatically unwraps the ResponseEnvelope<T> wrapper, so frontend callers receive the inner data object directly.