How to Integrate FastAPI for investment banking with LangChain for production AI
FastAPI gives you the HTTP surface for investment banking workflows: trade capture, approvals, client requests, risk checks, and audit-friendly APIs. LangChain gives you the orchestration layer for LLM-driven reasoning, tool calling, and structured outputs. Combined, you can build an AI agent that sits in front of banking systems and turns unstructured analyst requests into validated actions.
Prerequisites
- •Python 3.10+
- •FastAPI installed and configured
- •Uvicorn for local API serving
- •LangChain installed with your model provider package
- •A working LLM API key, such as OpenAI or Azure OpenAI
- •Pydantic v2
- •Basic knowledge of REST APIs and async Python
- •A sandbox or non-production banking backend to test against
Install the core packages:
pip install fastapi uvicorn langchain langchain-openai pydantic httpx
Integration Steps
- •Define the FastAPI contract for your banking workflow
Start with a narrow endpoint. In investment banking systems, the first mistake is exposing too much surface area to the agent.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title="Investment Banking AI API")
class TradeRequest(BaseModel):
client_id: str = Field(..., examples=["C12345"])
symbol: str = Field(..., examples=["AAPL"])
side: str = Field(..., pattern="^(buy|sell)$")
quantity: int = Field(..., gt=0)
class TradeResponse(BaseModel):
status: str
trade_id: str
message: str
@app.post("/trades", response_model=TradeResponse)
async def create_trade(req: TradeRequest):
if req.quantity > 100000:
raise HTTPException(status_code=400, detail="Quantity exceeds limit")
return TradeResponse(
status="accepted",
trade_id="TRD-20240421-001",
message=f"Trade queued for {req.client_id}"
)
This is the API LangChain will call through a tool wrapper. Keep the contract strict with Pydantic.
- •Wrap the FastAPI endpoint as a LangChain tool
LangChain tools are how the agent interacts with your backend. Use @tool for a clean interface.
import httpx
from langchain_core.tools import tool
BASE_URL = "http://localhost:8000"
@tool
async def submit_trade(client_id: str, symbol: str, side: str, quantity: int) -> dict:
"""Submit a trade request to the investment banking API."""
payload = {
"client_id": client_id,
"symbol": symbol,
"side": side,
"quantity": quantity,
}
async with httpx.AsyncClient() as client:
response = await client.post(f"{BASE_URL}/trades", json=payload)
response.raise_for_status()
return response.json()
This keeps your agent logic separate from transport concerns. The tool only knows how to call the API.
- •Build an agent that can choose when to call the banking tool
Use a chat model plus tool binding. For production, keep temperature low and constrain outputs.
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(
model="gpt-4o-mini",
temperature=0,
api_key=os.environ["OPENAI_API_KEY"],
)
tools = [submit_trade]
llm_with_tools = llm.bind_tools(tools)
async def run_agent(user_request: str):
messages = [HumanMessage(content=user_request)]
ai_msg = await llm_with_tools.ainvoke(messages)
return ai_msg
At this point the model can decide whether it needs to call submit_trade. In production, you usually add guardrails before execution.
- •Add an approval gate before executing trades
For investment banking use cases, don’t let the model execute directly without validation. Check policy first.
from pydantic import BaseModel
class ApprovalDecision(BaseModel):
approved: bool
reason: str
def approve_trade(client_id: str, symbol: str, quantity: int) -> ApprovalDecision:
restricted_symbols = {"GME", "AMC"}
if symbol in restricted_symbols:
return ApprovalDecision(approved=False, reason="Restricted symbol")
if quantity > 50000:
return ApprovalDecision(approved=False, reason="Manual review required")
return ApprovalDecision(approved=True, reason="Approved")
async def process_request(user_request: str):
# In practice parse structured intent first; simplified here.
decision = approve_trade("C12345", "AAPL", 1000)
if not decision.approved:
return {"status": "rejected", "reason": decision.reason}
result = await submit_trade.ainvoke({
"client_id": "C12345",
"symbol": "AAPL",
"side": "buy",
"quantity": 1000,
})
return result
This pattern matters more than prompt quality. Banking systems need deterministic controls around any AI action.
- •Expose the agent through FastAPI for downstream systems
Now wrap the orchestration in an API endpoint so other services can consume it.
from fastapi import Body
class AgentRequest(BaseModel):
request_text: str
@app.post("/agent/trade")
async def trade_agent(payload: AgentRequest = Body(...)):
result = await process_request(payload.request_text)
return result
This gives you one entry point for CRM tools, internal portals, or ops dashboards.
Testing the Integration
Run FastAPI:
uvicorn app:app --reload --port 8000
Then verify both layers work together:
import asyncio
import httpx
async def test_integration():
async with httpx.AsyncClient() as client:
resp = await client.post(
"http://localhost:8000/agent/trade",
json={"request_text": "Buy 1000 shares of AAPL for client C12345"}
)
print(resp.status_code)
print(resp.json())
asyncio.run(test_integration())
Expected output:
200
{'status': 'accepted', 'trade_id': 'TRD-20240421-001', 'message': 'Trade queued for C12345'}
If you get a rejection instead, confirm your approval rules and payload mapping.
Real-World Use Cases
- •
Trade request triage
- •Parse incoming emails or chat messages into structured trade intents.
- •Validate them against policy before routing to execution systems.
- •
Client servicing assistant
- •Answer questions about order status, holdings summaries, or onboarding steps.
- •Use LangChain to retrieve context and FastAPI to expose secure endpoints.
- •
Operations automation
- •Generate exception tickets from failed settlements or missing KYC fields.
- •Let the agent classify issues and call internal FastAPI services to create workflows.
The clean pattern is simple: FastAPI owns contracts and system boundaries, LangChain owns reasoning and tool selection. Keep approvals outside the model path where possible. That’s how you ship AI into investment banking without turning your API into a liability.
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