How to Integrate FastAPI for lending with PostgreSQL for AI agents

By Cyprian AaronsUpdated 2026-04-21
fastapi-for-lendingpostgresqlai-agents

FastAPI for lending gives you the API layer to expose loan workflows to your agent. PostgreSQL gives you durable state for applications, decisions, repayment schedules, and audit trails. Put them together and you get an AI agent system that can intake borrower data, score applications, persist decisions, and serve loan status without losing context between turns.

Prerequisites

  • Python 3.10+
  • A running PostgreSQL instance
  • A FastAPI app set up for your lending workflow
  • pip installed packages:
    • fastapi
    • uvicorn
    • psycopg2-binary or asyncpg
    • sqlalchemy
    • pydantic
  • A PostgreSQL database and credentials:
    • host
    • port
    • database name
    • username
    • password
  • Basic familiarity with REST endpoints and SQL schema design

Integration Steps

  1. Set up the PostgreSQL connection layer

For production systems, keep the DB layer separate from route handlers. Use SQLAlchemy so your FastAPI lending service can create, read, and update loan records cleanly.

from sqlalchemy import create_engine, Column, Integer, String, Numeric, DateTime, func
from sqlalchemy.orm import declarative_base, sessionmaker

DATABASE_URL = "postgresql+psycopg2://loan_user:loan_pass@localhost:5432/lending_db"

engine = create_engine(DATABASE_URL, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class LoanApplication(Base):
    __tablename__ = "loan_applications"

    id = Column(Integer, primary_key=True, index=True)
    applicant_name = Column(String(255), nullable=False)
    amount = Column(Numeric(12, 2), nullable=False)
    status = Column(String(50), nullable=False, default="pending")
    created_at = Column(DateTime(timezone=True), server_default=func.now())

Base.metadata.create_all(bind=engine)

This gives your lending agent a durable store for application state. If the agent restarts mid-flow, the record is still there.

  1. Build the FastAPI lending endpoint

Expose a route that accepts an application payload from your AI agent or orchestration layer. The endpoint writes directly to PostgreSQL through the session.

from fastapi import FastAPI, Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session

app = FastAPI(title="Lending API")

class LoanRequest(BaseModel):
    applicant_name: str
    amount: float

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/loans/apply")
def apply_for_loan(payload: LoanRequest, db: Session = Depends(get_db)):
    application = LoanApplication(
        applicant_name=payload.applicant_name,
        amount=payload.amount,
        status="pending",
    )
    db.add(application)
    db.commit()
    db.refresh(application)

    return {
        "application_id": application.id,
        "status": application.status,
        "amount": str(application.amount),
    }

This is the core integration point. Your AI agent can call /loans/apply, then use the returned application_id to track the case across later steps.

  1. Add decision persistence for the agent workflow

AI agents need more than intake. They need to store underwriting outcomes, manual review flags, and repayment plans in PostgreSQL so downstream tools can query them later.

from sqlalchemy import Boolean

class LoanDecision(Base):
    __tablename__ = "loan_decisions"

    id = Column(Integer, primary_key=True)
    application_id = Column(Integer, nullable=False, index=True)
    approved = Column(Boolean, nullable=False)
    reason = Column(String(500), nullable=False)

Base.metadata.create_all(bind=engine)

@app.post("/loans/{application_id}/decision")
def save_decision(application_id: int, approved: bool, reason: str, db: Session = Depends(get_db)):
    decision = LoanDecision(
        application_id=application_id,
        approved=approved,
        reason=reason,
    )
    db.add(decision)

    loan = db.query(LoanApplication).filter(LoanApplication.id == application_id).first()
    if loan:
        loan.status = "approved" if approved else "rejected"

    db.commit()
    return {"application_id": application_id, "approved": approved}

This pattern is useful when an LLM makes a recommendation but your system still needs a persistent audit trail.

  1. Query loan state from PostgreSQL inside FastAPI

Your agent will often need to fetch status before deciding what to do next. Add a read endpoint that returns current application state plus any stored decision.

@app.get("/loans/{application_id}")
def get_loan(application_id: int, db: Session = Depends(get_db)):
    loan = db.query(LoanApplication).filter(LoanApplication.id == application_id).first()
    decision = db.query(LoanDecision).filter(LoanDecision.application_id == application_id).first()

    if not loan:
        return {"error": "application not found"}

    return {
        "application_id": loan.id,
        "applicant_name": loan.applicant_name,
        "amount": str(loan.amount),
        "status": loan.status,
        "decision": {
            "approved": decision.approved,
            "reason": decision.reason,
        } if decision else None,
    }

This is the endpoint your agent calls before sending follow-up messages or triggering repayment workflows.

  1. Run the service and wire it into your AI agent

Start FastAPI with Uvicorn and let your agent call it over HTTP. In most production setups this will sit behind an internal gateway or service mesh.

# terminal command
uvicorn main:app --reload --host 0.0.0.0 --port 8000

If your agent uses Python tool-calling or a workflow engine like LangGraph or Celery tasks behind an orchestrator, point it at these endpoints as tools. The key is that the agent never stores critical lending state in memory only; PostgreSQL remains source of truth.

Testing the Integration

Use FastAPI’s test client to verify that data lands in PostgreSQL and can be read back.

from fastapi.testclient import TestClient

client = TestClient(app)

response = client.post("/loans/apply", json={
    "applicant_name": "Jane Doe",
    "amount": 15000
})
print(response.json())

loan_id = response.json()["application_id"]

lookup = client.get(f"/loans/{loan_id}")
print(lookup.json())

Expected output:

{
  "application_id": 1,
  "status": "pending",
  "amount": "15000"
}
{
  "application_id": 1,
  "applicant_name": "Jane Doe",
  "amount": "15000",
  "status": "pending",
  "decision": null
}

Real-World Use Cases

  • Automated lending intake

    • An AI agent collects borrower details over chat or email.
    • FastAPI validates the payload and writes it into PostgreSQL for underwriting review.
  • Decision support with auditability

    • The model recommends approve/reject/manual review.
    • PostgreSQL stores every decision with reasons for compliance and later analysis.
  • Servicing workflows

    • An agent checks repayment status before sending reminders or restructuring offers.
    • FastAPI reads current records from PostgreSQL and returns deterministic state to downstream systems.

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