How to Integrate Azure OpenAI for lending with CosmosDB for AI agents

By Cyprian AaronsUpdated 2026-04-21
azure-openai-for-lendingcosmosdbai-agents

Combining Azure OpenAI for lending with Cosmos DB gives you a practical pattern for building AI agents that can reason over loan data, retrieve customer context, and persist decisions or conversation state. The useful part is not just answering questions; it is keeping the agent grounded in borrower records, underwriting notes, and case history so every response is auditable and stateful.

For lending workflows, that means an agent can summarize applications, classify risk signals, draft follow-up messages, and write structured outputs back to Cosmos DB for downstream systems.

Prerequisites

  • An Azure subscription with:
    • Azure OpenAI resource
    • Azure Cosmos DB for NoSQL account
  • A deployed Azure OpenAI model for chat completions
    • Example: gpt-4o-mini or another chat model you approved for lending use cases
  • Cosmos DB database and container created
    • Example container partition key: /customerId
  • Python 3.10+
  • Installed packages:
    • azure-ai-openai
    • azure-cosmos
    • azure-core
    • python-dotenv
  • Environment variables configured:
    • AZURE_OPENAI_ENDPOINT
    • AZURE_OPENAI_API_KEY
    • AZURE_OPENAI_DEPLOYMENT
    • COSMOS_ENDPOINT
    • COSMOS_KEY
    • COSMOS_DATABASE_NAME
    • COSMOS_CONTAINER_NAME

Install the dependencies:

pip install azure-ai-openai azure-cosmos azure-core python-dotenv

Integration Steps

1) Load configuration and create client objects

Keep secrets out of code. Use environment variables and initialize both clients once at startup.

import os
from dotenv import load_dotenv
from azure.ai.openai import OpenAIClient
from azure.core.credentials import AzureKeyCredential
from azure.cosmos import CosmosClient

load_dotenv()

openai_client = OpenAIClient(
    endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    credential=AzureKeyCredential(os.environ["AZURE_OPENAI_API_KEY"])
)

cosmos_client = CosmosClient(
    url=os.environ["COSMOS_ENDPOINT"],
    credential=os.environ["COSMOS_KEY"]
)

database = cosmos_client.get_database_client(os.environ["COSMOS_DATABASE_NAME"])
container = database.get_container_client(os.environ["COSMOS_CONTAINER_NAME"])

deployment_name = os.environ["AZURE_OPENAI_DEPLOYMENT"]

2) Read borrower context from Cosmos DB

Your agent should never answer from the prompt alone. Pull the borrower record first so the model has current facts.

customer_id = "cust-10021"

borrower_doc = container.read_item(
    item=customer_id,
    partition_key=customer_id
)

print(borrower_doc)

A typical document might contain application status, income, debt-to-income ratio, previous interactions, and underwriting notes.

3) Send borrower context to Azure OpenAI for lending analysis

Use a system prompt that constrains the model to lending-specific behavior. Pass only the fields you need.

borrower_summary = {
    "customerId": borrower_doc["customerId"],
    "loanAmount": borrower_doc["loanAmount"],
    "annualIncome": borrower_doc["annualIncome"],
    "dti": borrower_doc["dti"],
    "creditScore": borrower_doc["creditScore"],
    "status": borrower_doc["status"]
}

messages = [
    {
        "role": "system",
        "content": (
            "You are a lending assistant. "
            "Summarize risk factors, identify missing information, "
            "and suggest next actions in a concise format."
        )
    },
    {
        "role": "user",
        "content": f"Analyze this loan application context: {borrower_summary}"
    }
]

response = openai_client.get_chat_completions(
    deployment_name=deployment_name,
    messages=messages,
    temperature=0.2,
    max_tokens=300
)

analysis_text = response.choices[0].message.content
print(analysis_text)

This pattern works well for agentic workflows because the model produces structured reasoning from live data instead of hallucinating a loan profile.

4) Persist the AI output back into Cosmos DB

Store the analysis as an event or decision record. That gives you traceability for audits and lets later agent steps reuse prior outputs.

from datetime import datetime, timezone

decision_record = {
    "id": f"{customer_id}-analysis-{datetime.now(timezone.utc).timestamp()}",
    "customerId": customer_id,
    "type": "loan_analysis",
    "createdAt": datetime.now(timezone.utc).isoformat(),
    "modelOutput": analysis_text,
    "sourceStatus": borrower_doc["status"]
}

container.upsert_item(decision_record)
print("Saved analysis to Cosmos DB")

If you are building a multi-step agent, this record becomes part of the system memory. A follow-up agent can read it before drafting an email or escalating to a human underwriter.

5) Build a simple end-to-end agent function

Wrap retrieval, inference, and persistence into one function your orchestration layer can call.

def analyze_loan_application(customer_id: str):
    doc = container.read_item(item=customer_id, partition_key=customer_id)

    messages = [
        {
            "role": "system",
            "content": (
                "You are a lending operations assistant. "
                "Return risk summary, missing fields, and recommended action."
            )
        },
        {
            "role": "user",
            "content": (
                f"Customer record: {doc}\n"
                f"Focus on underwriting signals and operational next steps."
            )
        }
    ]

    result = openai_client.get_chat_completions(
        deployment_name=deployment_name,
        messages=messages,
        temperature=0.1,
        max_tokens=250
    )

    output = result.choices[0].message.content

    container.upsert_item({
        "id": f"{customer_id}-latest-agent-output",
        "customerId": customer_id,
        "type": "agent_output",
        "output": output,
        "updatedAt": datetime.now(timezone.utc).isoformat()
    })

    return output


print(analyze_loan_application("cust-10021"))

Testing the Integration

Run a smoke test against one known customer record. You want to verify three things: read access from Cosmos DB, successful model invocation, and write-back persistence.

test_customer_id = "cust-10021"

result = analyze_loan_application(test_customer_id)
print("Agent result:")
print(result)

saved_item = container.read_item(
    item=f"{test_customer_id}-latest-agent-output",
    partition_key=test_customer_id
)

print("Persisted type:", saved_item["type"])

Expected output:

Agent result:
Risk summary: Moderate risk due to elevated DTI...
Missing fields: employment verification...
Recommended action: Request additional documents before proceeding.
Persisted type: agent_output

Real-World Use Cases

  • Loan intake triage
    • An agent reads application data from Cosmos DB, asks Azure OpenAI to classify completeness and risk, then writes a triage decision back for human review.
  • Borrower communication drafting
    • The agent pulls payment history or application status from Cosmos DB and generates compliant follow-up messages for missing documents or approval updates.
  • Underwriting memory layer
    • Store prior model outputs, reviewer notes, and exception handling in Cosmos DB so later agents can make decisions with full context instead of starting from scratch.

If you want this to hold up in production, keep prompts narrow, store every model decision as an immutable event, and treat Cosmos DB as your system of record for agent state. That is the difference between a demo and something lending teams can actually trust.


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