How to Integrate Anthropic for investment banking with pgvector for multi-agent systems

By Cyprian AaronsUpdated 2026-04-21
anthropic-for-investment-bankingpgvectormulti-agent-systems

Why this integration matters

If you’re building multi-agent systems for investment banking, you need two things: a strong reasoning model and durable retrieval over your firm’s private data. Anthropic gives you the model layer for drafting, summarizing, and analyzing financial context, while pgvector gives you low-latency semantic search over deal docs, CIMs, earnings notes, and internal research.

The combination is useful when one agent needs to answer a question from memory, then hand off grounded context to another agent that performs retrieval or validation. That’s the pattern you want for pitchbook support, diligence workflows, and internal research assistants.

Prerequisites

  • Python 3.10+
  • PostgreSQL 15+ with the pgvector extension installed
  • An Anthropic API key
  • A database user with permission to create tables and extensions
  • These Python packages:
    • anthropic
    • psycopg[binary]
    • pgvector
    • python-dotenv
  • A working embedding model strategy
    • Either use Anthropic for generation and a separate embedding model for vectors
    • Or route embeddings through your existing internal embedding service

Install the dependencies:

pip install anthropic psycopg[binary] pgvector python-dotenv

Integration Steps

1) Set up your environment and clients

Keep secrets out of code. For banking systems, use environment variables or a secrets manager.

import os
from dotenv import load_dotenv
from anthropic import Anthropic
import psycopg

load_dotenv()

anthropic_client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

conn = psycopg.connect(os.environ["DATABASE_URL"])
conn.autocommit = True

For multi-agent systems, I usually keep the LLM client and retrieval client separate. That makes it easier to swap models or databases without rewriting agent logic.

2) Enable pgvector and create a document table

You need a table that stores text plus embeddings. Use vector(1536) or whatever dimension matches your embedding model.

with conn.cursor() as cur:
    cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
    cur.execute("""
        CREATE TABLE IF NOT EXISTS banking_docs (
            id BIGSERIAL PRIMARY KEY,
            source TEXT NOT NULL,
            content TEXT NOT NULL,
            embedding vector(1536) NOT NULL
        );
    """)
    cur.execute("""
        CREATE INDEX IF NOT EXISTS banking_docs_embedding_idx
        ON banking_docs USING ivfflat (embedding vector_cosine_ops)
        WITH (lists = 100);
    """)

If you’re running this in production, load enough rows before relying on ivfflat. For small datasets, brute-force search is fine; for larger corpora, index tuning matters.

3) Insert documents with embeddings

Anthropic’s SDK is for generation, not embeddings. In practice, pair it with your embedding pipeline, then store vectors in pgvector.

Here’s a simple example using a placeholder embedding function. Replace it with your approved embedding provider or internal service.

from typing import List

def embed_text(text: str) -> List[float]:
    # Replace with your production embedding service.
    # Must return exactly 1536 floats if you're using vector(1536).
    return [0.0] * 1536

docs = [
    {
        "source": "Q4_Credit_Memo.pdf",
        "content": "The target company showed recurring revenue growth of 18% YoY..."
    },
    {
        "source": "Earnings_Call_Notes.txt",
        "content": "Management guided to margin expansion in H2 due to cost discipline..."
    }
]

with conn.cursor() as cur:
    for doc in docs:
        emb = embed_text(doc["content"])
        cur.execute(
            """
            INSERT INTO banking_docs (source, content, embedding)
            VALUES (%s, %s, %s)
            """,
            (doc["source"], doc["content"], emb)
        )

In a multi-agent setup, one agent can own ingestion while another handles query-time retrieval. That separation keeps your system easier to test and audit.

4) Retrieve relevant context from pgvector

Use cosine distance to fetch the most relevant documents for a question. This becomes the context passed into Anthropic.

def search_docs(query: str, limit: int = 3):
    query_emb = embed_text(query)

    with conn.cursor() as cur:
        cur.execute(
            """
            SELECT source, content
            FROM banking_docs
            ORDER BY embedding <=> %s::vector
            LIMIT %s;
            """,
            (query_emb, limit)
        )
        return cur.fetchall()

results = search_docs("What are the main margin drivers mentioned in the latest earnings notes?")
for source, content in results:
    print(source, content[:120])

This is the retrieval layer your agents should call before generating answers. Don’t let an analyst-facing agent answer from raw memory when you already have structured context in Postgres.

5) Call Anthropic with retrieved context

Now pass the retrieved snippets into Anthropic’s Messages API. This is where the model turns retrieved data into an investment-banking-ready response.

def answer_question(question: str) -> str:
    hits = search_docs(question)

    context_block = "\n\n".join(
        [f"Source: {source}\nContent: {content}" for source, content in hits]
    )

    message = anthropic_client.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=500,
        temperature=0,
        messages=[
            {
                "role": "user",
                "content": (
                    f"You are supporting an investment banking workflow.\n"
                    f"Use only the provided context.\n\n"
                    f"Context:\n{context_block}\n\n"
                    f"Question: {question}"
                ),
            }
        ],
    )

    return message.content[0].text

print(answer_question("Summarize the key operating trends and margin outlook."))

For multi-agent orchestration, this function becomes one tool among several. Another agent can validate numbers against source docs or generate follow-up questions for diligence.

Testing the Integration

Run a simple end-to-end check: insert one document, retrieve it by semantic similarity, then ask Anthropic to summarize it.

test_doc = {
    "source": "Test_Investor_Update.txt",
    "content": "Revenue increased by 22% year over year. EBITDA margin improved by 180 bps due to lower SG&A."
}

with conn.cursor() as cur:
    cur.execute(
        """
        INSERT INTO banking_docs (source, content, embedding)
        VALUES (%s, %s, %s)
        """,
        (test_doc["source"], test_doc["content"], embed_text(test_doc["content"]))
    )

print(answer_question("What changed in revenue and EBITDA margin?"))

Expected output:

Revenue increased by 22% year over year. EBITDA margin improved by 180 bps due to lower SG&A.

If retrieval works but the answer is vague, check three things:

  • Your embeddings have the correct dimension
  • Your query uses <=> for cosine distance consistently
  • Your prompt tells Claude to use only retrieved context

Real-World Use Cases

  • Deal team assistant

    • Search CIMs, diligence notes, and management presentations across multiple agents.
    • One agent retrieves facts from pgvector while Claude drafts banker-style summaries.
  • Earnings research workflow

    • Index transcripts and internal notes.
    • Let one agent fetch relevant passages and another produce concise takeaways for coverage teams.
  • Investment committee prep

    • Retrieve precedent deals, market comps commentary, and memo excerpts.
    • Use Claude to synthesize risks, catalysts, and open questions before committee review.

If you want this pattern to hold up in production at a bank or insurer:

  • Keep retrieval deterministic where possible
  • Log every query-document pair used in generation
  • Add row-level security if different desks should not see each other’s data

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