How to Integrate FastAPI for pension funds with LangChain for RAG
Opening
If you’re building an AI agent for pension operations, the pattern is simple: FastAPI handles the policy, member, and document APIs; LangChain handles retrieval and answer generation. Put them together, and you can build a RAG system that answers questions from pension documents, contribution history, benefit rules, and fund notices without hardcoding business logic into the model.
The value is in control. FastAPI gives you a clean service boundary for pension data, while LangChain lets you retrieve only the relevant context before generating a response.
Prerequisites
- •Python 3.10+
- •A FastAPI service exposing pension fund data or document endpoints
- •Access to your vector store of choice:
- •Chroma
- •FAISS
- •Pinecone
- •LangChain installed with your model provider package
- •An embedding model API key if you’re using hosted embeddings
- •A chat model API key if you’re using OpenAI, Anthropic, or similar
- •
uvicornfor local API testing
Install the core packages:
pip install fastapi uvicorn langchain langchain-openai langchain-community httpx pydantic
Integration Steps
- •Expose pension fund data through FastAPI
Start by wrapping your pension data in a service layer. For RAG, the important part is that your API returns structured text that can be chunked and indexed.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI(title="Pension Fund API")
class PensionDocument(BaseModel):
doc_id: str
title: str
content: str
PENSION_DOCS = {
"benefits-policy": {
"doc_id": "benefits-policy",
"title": "Benefits Policy",
"content": "Members may retire at age 55 subject to vesting rules and trustee approval."
},
"contribution-rules": {
"doc_id": "contribution-rules",
"title": "Contribution Rules",
"content": "Employer contributions are calculated monthly based on salary bands."
}
}
@app.get("/documents/{doc_id}", response_model=PensionDocument)
def get_document(doc_id: str):
doc = PENSION_DOCS.get(doc_id)
if not doc:
raise HTTPException(status_code=404, detail="Document not found")
return doc
@app.get("/documents")
def list_documents():
return list(PENSION_DOCS.values())
This gives your agent a stable contract. In production, this endpoint would pull from your CMS, policy store, or document management system.
- •Load pension documents from FastAPI into LangChain
Use httpx to call the FastAPI endpoints and convert the results into LangChain Document objects.
import httpx
from langchain_core.documents import Document
BASE_URL = "http://localhost:8000"
def fetch_pension_documents():
docs = []
with httpx.Client() as client:
response = client.get(f"{BASE_URL}/documents")
response.raise_for_status()
for item in response.json():
docs.append(
Document(
page_content=item["content"],
metadata={
"doc_id": item["doc_id"],
"title": item["title"],
"source": f"{BASE_URL}/documents/{item['doc_id']}"
}
)
)
return docs
pension_docs = fetch_pension_documents()
print(pension_docs[0].metadata)
This is the handoff point between your API layer and your retrieval layer. Keep the content normalized so chunking and retrieval stay predictable.
- •Build a vector index with LangChain
Index the documents using embeddings and a vector store. This example uses Chroma because it’s easy to run locally.
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=pension_docs,
embedding=embeddings,
collection_name="pension_fund_knowledge"
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
results = retriever.invoke("When can members retire?")
for doc in results:
print(doc.metadata["title"], doc.page_content)
For regulated environments, this is where you add access controls. Don’t index everything blindly if some documents are role-restricted.
- •Create a RAG chain with LangChain
Now connect retrieval to generation. Use a prompt that forces grounded answers and tells the model to say when the source material is insufficient.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.retrieval import create_retrieval_chain
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "You answer pension fund questions using only the provided context."),
("human", "Question: {input}\n\nContext:\n{context}")
])
document_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)
response = rag_chain.invoke({"input": "What is the retirement age?"})
print(response["answer"])
This keeps the model anchored to your pension policy content instead of guessing from general knowledge.
- •Expose the RAG chain as a FastAPI endpoint
Wrap the chain in an API so other services or agents can call it directly.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="Pension RAG API")
class QueryRequest(BaseModel):
question: str
@app.post("/ask")
def ask_pension_question(payload: QueryRequest):
result = rag_chain.invoke({"input": payload.question})
return {
"question": payload.question,
"answer": result["answer"]
}
This gives you one clean interface for downstream systems: CRM tools, advisor portals, internal copilots, or member self-service apps.
Testing the Integration
Run both services:
uvicorn app:app --reload --port 8000
Then test the RAG endpoint:
import requests
response = requests.post(
"http://localhost:8000/ask",
json={"question": "At what age can members retire?"}
)
print(response.status_code)
print(response.json())
Expected output:
{
"question": "At what age can members retire?",
"answer": "Members may retire at age 55 subject to vesting rules and trustee approval."
}
If you get a generic answer or hallucination, check three things:
- •Your retrieved document actually contains the answer
- •Your prompt restricts answers to context only
- •Your vector store is returning relevant chunks with
kset appropriately
Real-World Use Cases
- •
Member support assistant
- •Answer questions about retirement age, contribution schedules, vesting periods, and benefit eligibility from approved fund documents.
- •
Advisor copilot
- •Retrieve policy excerpts, plan rules, and historical notices for financial advisors handling pension inquiries.
- •
Operations knowledge search
- •Let internal staff query trustee resolutions, compliance notes, and fund communications through a controlled RAG interface.
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