How to Integrate Azure OpenAI for investment banking with CosmosDB for startups
Why this integration matters
If you’re building an AI agent for investment banking, Azure OpenAI gives you the reasoning layer: summarization, document extraction, deal memo drafting, and analyst-style Q&A. CosmosDB gives you the memory layer: low-latency storage for client profiles, deal context, conversation state, and retrieval data.
Put together, you get an agent that can read a pitch deck, persist structured deal notes, recall prior interactions, and generate banker-grade responses without losing context between sessions.
Prerequisites
- •Python 3.10+
- •An Azure subscription
- •An Azure OpenAI resource with:
- •a deployed chat model
- •endpoint URL
- •API key
- •An Azure Cosmos DB account
- •A Cosmos DB database and container
- •
pipinstalled - •Environment variables set:
- •
AZURE_OPENAI_ENDPOINT - •
AZURE_OPENAI_API_KEY - •
AZURE_OPENAI_DEPLOYMENT - •
COSMOS_ENDPOINT - •
COSMOS_KEY - •
COSMOS_DATABASE - •
COSMOS_CONTAINER
- •
Install the SDKs:
pip install openai azure-cosmos python-dotenv
Integration Steps
1) Configure credentials and clients
Start by loading environment variables and creating both clients. For Azure OpenAI, use the current AzureOpenAI client. For CosmosDB, use CosmosClient.
import os
from dotenv import load_dotenv
from openai import AzureOpenAI
from azure.cosmos import CosmosClient
load_dotenv()
azure_openai_client = AzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
api_version="2024-02-15-preview",
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
)
cosmos_client = CosmosClient(
os.environ["COSMOS_ENDPOINT"],
credential=os.environ["COSMOS_KEY"]
)
database_name = os.environ["COSMOS_DATABASE"]
container_name = os.environ["COSMOS_CONTAINER"]
database = cosmos_client.get_database_client(database_name)
container = database.get_container_client(container_name)
Use a dedicated container for agent memory. In banking workflows, don’t mix raw documents and conversational state in the same container unless your partitioning strategy is deliberate.
2) Create a deal-context schema in CosmosDB
Store structured data so the agent can retrieve it later. A common pattern is one document per deal or client interaction.
from datetime import datetime, timezone
def upsert_deal_context(deal_id: str, client_name: str, summary: str, risk_flags: list[str]):
item = {
"id": deal_id,
"dealId": deal_id,
"clientName": client_name,
"summary": summary,
"riskFlags": risk_flags,
"updatedAt": datetime.now(timezone.utc).isoformat()
}
return container.upsert_item(item)
deal_context = upsert_deal_context(
deal_id="deal-001",
client_name="Northstar Capital",
summary="Preparing acquisition financing for a mid-market software target.",
risk_flags=["high leverage", "tight covenant package"]
)
print(deal_context)
For startup systems, this becomes your agent memory store. For investment banking use cases, it’s also your audit trail for what the model knew when it produced an answer.
3) Pull context from CosmosDB before calling Azure OpenAI
Fetch stored context first, then inject it into the prompt. This is how you keep responses grounded in prior deal state.
def get_deal_context(deal_id: str):
query = """
SELECT * FROM c WHERE c.dealId = @deal_id
"""
items = list(container.query_items(
query=query,
parameters=[{"name": "@deal_id", "value": deal_id}],
enable_cross_partition_query=True
))
return items[0] if items else None
context = get_deal_context("deal-001")
messages = [
{
"role": "system",
"content": (
"You are an investment banking assistant. "
"Be concise, precise, and format outputs like an internal analyst note."
)
},
{
"role": "user",
"content": f"""
Deal context:
Client: {context['clientName']}
Summary: {context['summary']}
Risk flags: {', '.join(context['riskFlags'])}
Draft a 5-bullet financing recommendation.
"""
}
]
This pattern matters because Azure OpenAI should not be guessing from scratch. The model performs better when you provide structured state from CosmosDB instead of stuffing everything into free-form chat history.
4) Call Azure OpenAI and persist the response back to CosmosDB
Use chat.completions.create() to generate the answer, then store the result in CosmosDB for later retrieval.
response = azure_openai_client.chat.completions.create(
model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
messages=messages,
temperature=0.2,
)
recommendation = response.choices[0].message.content
audit_record = {
"id": f"note-{context['id']}",
"dealId": context["dealId"],
"type": "financing_recommendation",
"content": recommendation,
"createdAt": datetime.now(timezone.utc).isoformat()
}
container.upsert_item(audit_record)
print(recommendation)
That gives you two important properties:
- •repeatable generation with controlled temperature
- •durable storage of outputs for review, compliance checks, or human approval workflows
5) Wrap it as an agent function
In production, your orchestration layer should expose one function that retrieves context, calls the model, and saves results.
def generate_banking_note(deal_id: str) -> str:
context = get_deal_context(deal_id)
if not context:
raise ValueError(f"No context found for {deal_id}")
messages = [
{
"role": "system",
"content": (
"You are an investment banking copilot. "
"Write in bullet points and avoid speculation."
)
},
{
"role": "user",
"content": f"""
Client: {context['clientName']}
Summary: {context['summary']}
Risk flags: {', '.join(context['riskFlags'])}
Produce a short IC-ready recommendation.
"""
}
]
result = azure_openai_client.chat.completions.create(
model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
messages=messages,
temperature=0.1,
)
output = result.choices[0].message.content
container.upsert_item({
"id": f"output-{deal_id}",
"dealId": deal_id,
"type": "ic_note",
"content": output,
"createdAt": datetime.now(timezone.utc).isoformat()
})
return output
This is the shape you want for an AI agent system: retrieve state from CosmosDB, reason with Azure OpenAI, write results back to CosmosDB.
Testing the Integration
Run a simple end-to-end check that writes context, generates a response, and verifies persistence.
if __name__ == "__main__":
upsert_deal_context(
deal_id="deal-test-001",
client_name="Summit Bridge Partners",
summary="Evaluating debt financing options for a healthcare services acquisition.",
risk_flags=["regulatory exposure", "seasonality"]
)
note = generate_banking_note("deal-test-001")
print("\nGenerated Note:\n", note)
saved = get_deal_context("deal-test-001")
print("\nStored Context:\n", saved["summary"])
Expected output:
Generated Note:
- Recommend conservative leverage given regulatory exposure.
- Structure covenants with headroom around seasonal cash flow volatility.
- Consider staggered maturity profile to reduce refinancing risk.
- Require enhanced diligence on reimbursement concentration.
- Keep lender group tight to preserve execution speed.
Stored Context:
Evaluating debt financing options for a healthcare services acquisition.
Real-World Use Cases
- •
Deal memo assistant
Ingest client notes into CosmosDB, ask Azure OpenAI to draft an IC summary, then store each revision with timestamps for review workflows. - •
RFP and pitch support
Save firm capabilities and prior responses in CosmosDB so the model can generate tailored bank responses without hallucinating firm-specific facts. - •
Analyst copilot for CRM-linked workflows
Use CosmosDB as session memory across meetings and tasks so the agent can summarize prior discussions and produce next-step action items on demand.
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