How to Integrate Anthropic for lending with pgvector for production AI
Combining Anthropic for lending with pgvector gives you a practical pattern for production AI agents: use Anthropic to reason over lending workflows, then use pgvector to retrieve policy, borrower history, and document embeddings from your own database. That gives you grounded answers, better auditability, and a clean way to keep sensitive lending context inside your infrastructure.
For lending teams, this is the difference between a chat demo and an agent that can actually support underwriting, collections, and loan servicing with retrieval-backed responses.
Prerequisites
- •Python 3.10+
- •PostgreSQL 14+ with the
pgvectorextension enabled - •An Anthropic API key
- •Access to your lending knowledge base:
- •policy documents
- •underwriting rules
- •loan product docs
- •customer support playbooks
- •Python packages:
- •
anthropic - •
psycopg[binary] - •
pgvector - •
openaior another embedding provider if you are not using Anthropic for embeddings
- •
- •A network path to your database from the application runtime
Install the dependencies:
pip install anthropic psycopg[binary] pgvector numpy
Integration Steps
1) Set up pgvector in PostgreSQL
Create the extension and a table for embedded lending documents. Use a vector dimension that matches your embedding model.
import psycopg
conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/lending")
conn.execute("CREATE EXTENSION IF NOT EXISTS vector")
conn.execute("""
CREATE TABLE IF NOT EXISTS lending_docs (
id SERIAL PRIMARY KEY,
doc_type TEXT NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL,
embedding vector(1536)
)
""")
conn.commit()
conn.close()
If you are using a different embedding model dimension, change vector(1536) accordingly.
2) Generate embeddings and store them in pgvector
Anthropic’s API is used for reasoning and generation; for embeddings, use a dedicated embedding model. The pattern stays the same: convert lending text into vectors, then persist them in PostgreSQL.
import psycopg
from pgvector.psycopg import register_vector
from openai import OpenAI
client = OpenAI()
docs = [
{
"doc_type": "policy",
"title": "Debt-to-income rule",
"content": "Applicants with DTI above 43% require manual review unless compensating factors exist."
},
{
"doc_type": "servicing",
"title": "Late payment handling",
"content": "If payment is more than 15 days late, notify the borrower and create a follow-up task."
}
]
def embed(text: str):
resp = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return resp.data[0].embedding
conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/lending")
register_vector(conn)
for doc in docs:
vec = embed(f"{doc['title']}\n{doc['content']}")
conn.execute(
"""
INSERT INTO lending_docs (doc_type, title, content, embedding)
VALUES (%s, %s, %s, %s)
""",
(doc["doc_type"], doc["title"], doc["content"], vec)
)
conn.commit()
conn.close()
This gives you a searchable knowledge base for retrieval augmented generation.
3) Retrieve relevant lending context with pgvector
When a user asks a question about lending policy or loan handling, pull the closest matches first. That keeps Anthropic grounded in your internal data.
import psycopg
from pgvector.psycopg import register_vector
from openai import OpenAI
client = OpenAI()
def embed(text: str):
resp = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return resp.data[0].embedding
query = "Can we approve an applicant with high DTI if they have strong reserves?"
conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/lending")
register_vector(conn)
qvec = embed(query)
rows = conn.execute(
"""
SELECT title, content
FROM lending_docs
ORDER BY embedding <-> %s
LIMIT 3
""",
(qvec,)
).fetchall()
context = "\n\n".join([f"Title: {r[0]}\nContent: {r[1]}" for r in rows])
conn.close()
The <-> operator is the standard pgvector distance operator used for nearest-neighbor search.
4) Send retrieved context to Anthropic for a grounded answer
Now pass the retrieved lending context into Anthropic’s Messages API. This is where the agent reasons over policy and produces an answer suitable for an operations workflow.
from anthropic import Anthropic
anthropic_client = Anthropic(api_key="YOUR_ANTHROPIC_API_KEY")
response = anthropic_client.messages.create(
model="claude-3-5-sonnet-latest",
max_tokens=300,
messages=[
{
"role": "user",
"content": f"""
You are assisting with lending operations.
Use only the provided context to answer.
Context:
{context}
Question:
{query}
"""
}
]
)
print(response.content[0].text)
In production, keep the system prompt strict:
- •cite source documents when possible
- •refuse to invent policy not present in retrieved context
- •route ambiguous cases to manual review
5) Wrap it into a reusable agent function
Put retrieval + generation behind one function so your application can call it from an API endpoint or workflow engine.
import psycopg
from pgvector.psycopg import register_vector
from openai import OpenAI
from anthropic import Anthropic
embed_client = OpenAI()
anthropic_client = Anthropic(api_key="YOUR_ANTHROPIC_API_KEY")
def embed(text: str):
resp = embed_client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return resp.data[0].embedding
def answer_lending_question(question: str) -> str:
conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/lending")
register_vector(conn)
qvec = embed(question)
rows = conn.execute(
"""
SELECT title, content
FROM lending_docs
ORDER BY embedding <-> %s
LIMIT 5
""",
(qvec,)
).fetchall()
conn.close()
context = "\n\n".join([f"Title: {t}\nContent: {c}" for t, c in rows])
resp = anthropic_client.messages.create(
model="claude-3-5-sonnet-latest",
max_tokens=300,
messages=[
{
"role": "user",
"content": f"Answer using only this context:\n\n{context}\n\nQuestion: {question}"
}
]
)
return resp.content[0].text.strip()
print(answer_lending_question("What happens when DTI is above threshold?"))
Testing the Integration
Run one end-to-end query and verify that retrieval returns relevant docs before Claude answers.
result = answer_lending_question("Can an applicant over our DTI threshold still be reviewed?")
print(result)
Expected output:
Applicants with DTI above 43% require manual review unless compensating factors exist.
If you get an empty or generic answer:
- •check that embeddings were inserted into pgvector correctly
- •confirm your vector dimension matches the model output size
- •verify your prompt restricts Claude to retrieved context only
Real-World Use Cases
- •
Underwriting copilot
Pull policy docs and borrower notes from pgvector, then have Anthropic draft a recommendation with rationale and escalation flags. - •
Loan servicing assistant
Retrieve servicing procedures, late-fee rules, and communication templates so agents can respond consistently to borrower requests. - •
Compliance Q&A bot
Search internal lending policies by semantic meaning instead of keyword matching, then generate answers tied to source material for audit trails.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
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