How to Build a policy Q&A Agent Using LlamaIndex in TypeScript for investment banking

By Cyprian AaronsUpdated 2026-04-21
policy-q-allamaindextypescriptinvestment-bankingpolicy-qanda

A policy Q&A agent for investment banking answers questions about internal policies, procedures, and regulatory controls from approved source documents. It matters because bankers need fast answers on things like trading restrictions, information barriers, retention rules, and client communication policy without exposing sensitive material or relying on tribal knowledge.

Architecture

  • Policy document ingestion

    • Pull PDFs, DOCX files, and HTML policy pages from approved repositories.
    • Normalize them into text with metadata like policy owner, version, effective date, jurisdiction, and business line.
  • Indexing layer

    • Use VectorStoreIndex for semantic retrieval over policy content.
    • Keep document metadata attached so answers can be filtered by region, desk, or policy family.
  • Retriever + response synthesizer

    • Use a retriever to fetch the most relevant chunks.
    • Use ResponseSynthesizer through the query engine so the model answers only from retrieved context.
  • LLM gateway

    • Route requests through an approved model endpoint.
    • Enforce prompt templates that require citations and refuse unsupported claims.
  • Audit and logging

    • Store question text, retrieved document IDs, answer text, timestamps, user identity, and policy version used.
    • This is non-negotiable for compliance review and incident investigation.
  • Access control layer

    • Filter results by user role, desk, geography, and data classification.
    • A compliance analyst should not get the same corpus as a front-office user.

Implementation

  1. Install the TypeScript packages and set up your environment

Use the TypeScript SDK plus a local or managed vector store. For a real banking deployment, keep embeddings and source docs inside your approved data boundary.

npm install llamaindex dotenv

Set your environment variables:

OPENAI_API_KEY=your_key
  1. Load policy documents with metadata

The key pattern is to preserve metadata from ingestion. In investment banking, you need to know which policy version produced an answer when audit asks six months later.

import "dotenv/config";
import {
  Document,
  VectorStoreIndex,
  Settings,
  OpenAI,
} from "llamaindex";

Settings.llm = new OpenAI({
  model: "gpt-4o-mini",
});

const docs = [
  new Document({
    text: `
      Employees must not discuss pending capital markets transactions outside approved channels.
      Public side and private side information must remain separated at all times.
    `,
    metadata: {
      title: "Information Barriers Policy",
      version: "2025.01",
      businessLine: "Investment Banking",
      jurisdiction: "US",
      owner: "Compliance",
    },
  }),
  new Document({
    text: `
      Client communications related to live deals require pre-clearance where mandated by desk procedure.
      Retain approved communications according to records management schedule.
    `,
    metadata: {
      title: "Client Communications Policy",
      version: "2025.02",
      businessLine: "Investment Banking",
      jurisdiction: "UK",
      owner: "Legal",
    },
  }),
];

const index = await VectorStoreIndex.fromDocuments(docs);
  1. Build a query engine that answers with grounded context

This is the core pattern. The agent should retrieve relevant chunks first, then synthesize an answer from those chunks only.

const queryEngine = index.asQueryEngine({
  similarityTopK: 3,
});

const question = `
Can I discuss a live ECM mandate with someone on the public side?
`;

const response = await queryEngine.query({
  query: question,
});

console.log(String(response));

That gives you the baseline. In production, wrap this in a service layer that adds identity checks, policy filters, and audit logging before calling query().

  1. Add a guardrailed answer format with citations

For banking use cases, plain prose is not enough. You want the answer to cite the source documents so compliance can trace every claim back to policy text.

const citedEngine = index.asQueryEngine({
  similarityTopK: 3,
});

const citedResponse = await citedEngine.query({
  query:
    "What is the rule for discussing pending transactions across public and private sides?",
});

console.log({
  answer: String(citedResponse),
});

In practice, pair this with prompt instructions in your LLM configuration that force short answers like:

  • direct answer
  • applicable policy name/version
  • citation or source reference
  • escalation path if uncertain

Production Considerations

  • Data residency

    • Keep embeddings, indexes, and logs in-region if your bank has UK/EU/US segregation requirements.
    • Do not send restricted policies to unmanaged external services.
  • Auditability

    • Log userId, timestamp, query text, retrieved document IDs, policy versions, and final answer.
    • Preserve enough detail to reconstruct why the agent answered what it did.
  • Guardrails

    • Add a refusal path for questions outside policy scope or requests for legal advice.
    • If retrieval confidence is low, return “I couldn’t find support in approved policies” instead of guessing.
  • Access control

    • Filter documents before retrieval based on entitlements.
    • A M&A banker asking about research conflict rules should not see HR-only disciplinary guidance unless authorized.

Common Pitfalls

  • Skipping metadata during ingestion

    • If you lose version, owner, jurisdiction, or business line tags, you cannot defend the answer later.
    • Fix it by attaching structured metadata on every Document.
  • Letting the model answer without retrieval grounding

    • A general-purpose LLM will confidently invent policy details.
    • Fix it by forcing all answers through VectorStoreIndex.asQueryEngine() and rejecting unsupported responses.
  • Ignoring policy drift

    • Banking policies change often due to regulatory updates and internal controls refreshes.
    • Fix it with scheduled re-indexing and versioned documents so old answers do not survive new rules.

A solid investment banking policy Q&A agent is mostly about control points: controlled sources, controlled retrieval, controlled output. If you get those right with LlamaIndex in TypeScript, you end up with something compliance can actually sign off on instead of another chatbot demo that breaks under review.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides