Pramiti Docs

Data Flow

Request lifecycle for NLQ queries and action validation

This page traces the complete lifecycle of the two primary operations: asking a question (read plane) and validating an action (write plane).

NLQ Query Flow (Read Plane)

When an agent asks "What is our monthly revenue by customer?":

1. Agent → MCP ask_question("What is our monthly revenue by customer?")

2. │→ Query Router: classify_intent()
   │   Result: "analytical" (requires SQL generation)

3. │→ Verified Query Loader: find_relevant()
   │   Result: 2 matching VQs about revenue

4. │→ Prompt Assembler: build context window
   │   Includes:
   │   - Schema: invoices(id, customer_id, net_amount, status, created_at)
   │   - Definition: "Revenue = net_amount WHERE status = 'paid'"
   │   - VQ examples: 2 verified patterns
   │   - Business rules: "Exclude credits and refunds"

5. │→ LLM (Claude): generate SQL from context
   │   Output: SELECT c.name, SUM(i.net_amount) FROM invoices i
   │           JOIN customers c ON i.customer_id = c.id
   │           WHERE i.status = 'paid'
   │           GROUP BY c.name

6. │→ SQL Validator: validate_sql()
   │   Checks: column existence ✓, join paths ✓, PII columns ✗, anti-patterns ✗
   │   Result: PASS

7. │→ Database Connector: execute SQL
   │   Source: production_postgres
   │   Timeout: EPISTOM_QUERY_TIMEOUT_SECONDS
   │   Row limit: EPISTOM_MAX_QUERY_ROWS

8. │→ PII Gate: scan results for PII patterns
   │   Result: no PII detected

9. │→ Query Logger: persist outcome
   │   Stores: question, SQL, results hash, confidence, timing

10.└→ Agent receives:
       {
         "answer": "Monthly revenue by customer",
         "sql": "SELECT ...",
         "data": [...],
         "confidence": 0.92,
         "query_id": "q-abc123"
       }

If Validation Fails

At step 6, if the SQL validator rejects the query:

6a. SQL Validator: FAIL — column 'revenue' does not exist

6b. Self-Correction: append error context to prompt

6c. LLM: regenerate SQL with corrections

6d. SQL Validator: re-validate (up to 2 retries)

Action Validation Flow (Write Plane)

When an agent proposes salesforce.update_contact({contact_id: "123", amount: 50000}):

1. Agent → MCP tool call: salesforce.update_contact

2. │→ MCP Gate: intercept tool call
   │   Agent identity: "sales-bot-1" (from headers)

3. │→ Tool Classifier: classify("salesforce.update_contact")
   │   Result: ACTION (requires evaluation)

4. │→ Policy Engine: evaluate constraints
   │   Matching constraints:
   │   - "salesforce.update_*: amount <= 10000" → FAIL
   │   - "salesforce.*: status != deleted" → PASS
   │   Result: DENY (amount 50000 > 10000 cap)

5. │→ Impact Engine: compute blast radius
   │   Affected: Salesforce CRM (direct), Data Warehouse (cascade)
   │   Severity: medium
   │   Rollback: possible (Salesforce versioning)

6. │→ Attestation Store: record decision
   │   Signature: Ed25519(verdict + tool + agent + payload_hash + impact_hash)
   │   Storage: INSERT INTO aegis_attestations (append-only)

7. │→ SIEM Enqueue: write delivery rows
   │   Destinations: Splunk HEC, Sentinel (best-effort)

8. └→ Agent receives:
       {
         "verdict": "deny",
         "reason": "Amount 50000 exceeds cap of 10000 for salesforce.update_*",
         "attestation_id": "att-xyz789"
       }

REWRITE Flow

If the constraint specifies a REWRITE instead of DENY:

4a. Policy Engine: REWRITE verdict
    Rewrites: [{"op": "cap_value", "field": "amount", "max": 10000}]

4b. Rewrite Engine: apply transformations
    Original: {amount: 50000} → Modified: {amount: 10000}

4c. Attestation Store: record both original and modified payloads

4d. Execute with modified payload → salesforce.update_contact({amount: 10000})

Timing

Typical latencies:

StepP50P99
Query routing2ms10ms
VQ matching5ms20ms
LLM generation800ms3000ms
SQL validation10ms50ms
SQL execution50ms500ms
Policy evaluation3ms15ms
Attestation write5ms20ms
SIEM enqueue2ms10ms

On this page