Deploy Your First AI Agent on Azure
Build a production-ready AI agent in one day. No fluff, pure practical guidance.
Read the Contoso Case Study first if you want real-world business context. It shows why you'd make these architectural choices. But if you prefer learning by doing, jump straight in below.
Getting Started
Deploy an AI agent that's safe, stateful, and grounded in real data.
You want to deploy an AI agent on Azure. Where do you start? This guide walks you through the essentials: deployment decisions, safety setup, conversation memory, and knowledge grounding. By the end, you'll have a working blueprint.
🎯 The 30-Second Overview
An AI agent needs four things:
| Layer | Purpose | Learn More |
|---|---|---|
| Deployment | Choose infrastructure (scale, cost, compliance) | 5 Critical Decisions |
| Safety | Prevent jailbreaks, content filtering, tool approval | Agent Configuration |
| Memory | Remember conversations, build context | Coming soon |
| Knowledge | Ground responses in real data (RAG) | Knowledge Grounding |
🚀 Choose Your Deployment Approach
Option A: 🎨 UI-Based (Azure Foundry Studio)
Best for: Quick setup, visual interface, no coding
- Go to Azure Foundry Studio
- Create new project
- Select model (e.g., gpt-4o)
- Configure safety settings
- Click "Deploy"
No code needed. You get a working agent in minutes.
👉 See UI Tutorial (Microsoft Learn)
Option B: 💻 Code-Based (Python SDK)
Best for: Production workflows, automation, complete control, integration with existing systems
This walkthrough shows Option B with Python SDK and async patterns for production readiness. All code is copy-paste ready and uses Managed Identity (no API keys needed).
- Azure CLI: Use
az foundrycommands for scripted deployment - Terraform/Bicep: Infrastructure-as-code for CI/CD pipelines
- REST API: Direct Azure Resource Manager calls
See Deployment Types & Decisions for infrastructure patterns.
🚀 Option B: Code-Based Deployment with Python SDK
Step 0: Prerequisites
Before you start, you need:
# Install Python packages
pip install azure-ai-openai azure-identity azure-cosmos azure-search-documents
# Set environment variables (no API keys!)
export AZURE_OPENAI_ENDPOINT="https://your-openai.openai.azure.com/"
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o"
export AZURE_COSMOS_ENDPOINT="https://your-cosmos.documents.azure.com:443/"
export AZURE_SEARCH_ENDPOINT="https://your-search.search.windows.net"
Step 1: Deploy & Connect to the Model
Create and connect to Azure OpenAI using Managed Identity (no API keys):
from azure.ai.openai import AzureOpenAI
from azure.identity import DefaultAzureCredential
# ✅ Use Managed Identity - Azure handles auth automatically
credential = DefaultAzureCredential()
client = AzureOpenAI(
api_version="2024-08-01-preview",
endpoint="https://your-openai.openai.azure.com/", # Your region
credential=credential
)
# Test: Send a simple message
response = client.chat.completions.create(
model="gpt-4o", # Your deployed model name
messages=[
{"role": "user", "content": "Hello! What's 2+2?"}
]
)
print(f"✅ Model responded: {response.choices[0].message.content}")
What this does:
- Connects to your Azure OpenAI resource
- Uses Managed Identity (secure, no credentials in code)
- Sends a test message and gets a response
Next level (detailed decisions): 5 Critical Deployment Decisions
Step 2: Add Safety Evaluation
Before processing user input, evaluate it for safety:
# For learning: Here's a simple safety check pattern
# For production: See [Agent Configuration Overview](../agent-configuration/agent-configuration-overview)
def evaluate_user_input(user_message: str) -> dict:
"""
Simple safety evaluation pattern.
Production implementation uses Azure Content Safety service.
"""
# Pattern 1: Length check (prevent prompt injection)
if len(user_message) > 1000:
return {"safe": False, "reason": "input_too_long"}
# Pattern 2: Blocklist check
blocklist = ["password", "api_key", "credit_card"]
if any(term in user_message.lower() for term in blocklist):
return {"safe": False, "reason": "blocked_terms"}
# Pattern 3: Jailbreak pattern detection
jailbreak_patterns = ["ignore previous", "pretend you are", "act like"]
if any(pattern in user_message.lower() for pattern in jailbreak_patterns):
return {"safe": False, "reason": "jailbreak_attempt"}
return {"safe": True, "reason": "ok"}
# Use it
user_input = "What's the weather?"
safety_check = evaluate_user_input(user_input)
if safety_check["safe"]:
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": user_input}]
)
print(f"Response: {response.choices[0].message.content}")
else:
print(f"⚠️ Input blocked: {safety_check['reason']}")
What this does:
- Checks for injection attempts
- Blocks sensitive terms
- Detects jailbreak patterns
- Rejects unsafe input
For production safety (content filtering, jailbreak detection): Agent Configuration Overview
Step 3: Add Conversation Memory
Store conversations so the agent remembers context:
from azure.cosmos.aio import CosmosClient
from azure.identity import DefaultAzureCredential
import uuid
from datetime import datetime
import asyncio
credential = DefaultAzureCredential()
async def init_cosmos():
"""Initialize Cosmos DB connection"""
cosmos_client = CosmosClient(
url="https://your-cosmos.documents.azure.com:443/",
credential=credential
)
# Get database and container
database = cosmos_client.get_database_client("agent_db")
container = database.get_container_client("conversations")
return container
async def save_conversation(container, customer_id: str, question: str, answer: str):
"""Save a conversation turn to memory"""
conversation_item = {
"id": str(uuid.uuid4()),
"customer_id": customer_id,
"timestamp": datetime.utcnow().isoformat(),
"question": question,
"answer": answer
}
await container.upsert_item(conversation_item)
print(f"✅ Saved conversation for customer {customer_id}")
async def get_conversation_history(container, customer_id: str, limit: int = 5):
"""Retrieve previous conversations for context"""
query = "SELECT * FROM c WHERE c.customer_id = @cid ORDER BY c.timestamp DESC"
items = container.query_items(
query=query,
parameters=[{"name": "@cid", "value": customer_id}]
)
history = []
async for item in items:
if len(history) >= limit:
break
history.append(item)
return list(reversed(history)) # Chronological order
# Use it
async def example_with_memory():
container = await init_cosmos()
customer_id = "customer_123"
# Get previous context
history = await get_conversation_history(container, customer_id)
# Build system prompt with context
system_prompt = "You are a helpful assistant. Remember: "
for conv in history:
system_prompt += f"Previously: {conv['question'][:30]}... "
# Get response
response = client.chat.completions.create(
model="gpt-4o",
system=system_prompt,
messages=[
{"role": "user", "content": "What did we discuss before?"}
]
)
answer = response.choices[0].message.content
# Save for next time
await save_conversation(
container,
customer_id,
"What did we discuss before?",
answer
)
# Run it
asyncio.run(example_with_memory())
What this does:
- Connects to Cosmos DB (conversation store)
- Saves each conversation turn
- Retrieves previous context for personalization
- Includes context in agent prompt
For detailed memory patterns: Coming soon - Memory & Conversation Topics
Step 4: Add Knowledge Grounding (RAG)
Enable semantic search over your data:
from azure.search.documents.aio import SearchClient
from azure.search.documents.models import VectorizedQuery
import asyncio
async def search_knowledge_base(query: str, top_k: int = 3) -> list:
"""Find relevant information using semantic search"""
search_client = SearchClient(
endpoint="https://your-search.search.windows.net",
index_name="products", # Your index name
credential=credential
)
# For this example, using text search
# Production uses vector embeddings - see Knowledge Grounding article
results = await search_client.search(
search_text=query,
select=["content", "source"],
top=top_k
)
docs = []
async for result in results:
docs.append({
"content": result["content"],
"source": result["source"]
})
return docs
async def agent_with_knowledge():
"""Query agent with knowledge grounding"""
# User asks a question
user_question = "What's your warranty policy?"
# Retrieve relevant knowledge
knowledge_docs = await search_knowledge_base(user_question)
# Build context from knowledge
knowledge_context = "Based on our documentation:\n\n"
for doc in knowledge_docs:
knowledge_context += f"- {doc['content']}\n"
# Ask agent with grounding
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": f"Answer based ONLY on this information:\n{knowledge_context}"
},
{
"role": "user",
"content": user_question
}
]
)
print(f"✅ Grounded answer: {response.choices[0].message.content}")
# Run it
asyncio.run(agent_with_knowledge())
What this does:
- Searches your knowledge base (AI Search index)
- Retrieves relevant documents
- Grounds agent response in real data
- Reduces hallucinations
For complete RAG setup (embeddings, vector indexing, chunking): Knowledge Grounding Overview
Step 5: Bring It All Together
async def full_agent_example():
"""Complete agent: deployment + safety + memory + knowledge"""
# Initialize
container = await init_cosmos()
customer_id = "customer_456"
# User input
user_message = "Do you have the blue widget in stock?"
# Step 1: Safety check
safety = evaluate_user_input(user_message)
if not safety["safe"]:
print(f"⚠️ Rejected: {safety['reason']}")
return
# Step 2: Get memory context
history = await get_conversation_history(container, customer_id, limit=3)
# Step 3: Search knowledge base
knowledge = await search_knowledge_base(user_message)
# Step 4: Build prompt with all context
knowledge_text = "\n".join([f"- {doc['content']}" for doc in knowledge])
system_prompt = f"""You are a helpful product assistant.
Use ONLY this knowledge base:
{knowledge_text}
Previous context:"""
for conv in history:
system_prompt += f"\n- User asked: {conv['question'][:40]}..."
# Step 5: Get response from model
response = client.chat.completions.create(
model="gpt-4o",
system=system_prompt,
messages=[
{"role": "user", "content": user_message}
]
)
answer = response.choices[0].message.content
print(f"Agent: {answer}")
# Step 6: Save to memory
await save_conversation(container, customer_id, user_message, answer)
# Run it
asyncio.run(full_agent_example())
✅ What You Just Built
You now have a working agent with:
- ✅ Model deployment (Azure OpenAI)
- ✅ Safety evaluation (input validation)
- ✅ Conversation memory (Cosmos DB)
- ✅ Knowledge grounding (AI Search)
- ✅ Secure auth (Managed Identity)
Each piece can be enhanced by reading the detailed articles.
📚 Next: Go Deeper
| Topic | Why Read | Level |
|---|---|---|
| 5 Critical Deployment Decisions | Make the right infrastructure choices for YOUR situation | Architecture |
| Agent Configuration | Production-grade safety, jailbreak detection, tool controls | Deep Dive |
| Knowledge Grounding | Vector embeddings, chunking strategies, semantic search | Deep Dive |
| Contoso Case Study (optional) | See real-world enterprise requirements | Context |
Last updated: 2026-09-28
🎓 Ready to Code?
Pick a topic and dive in:
- 5 Critical Deployment Decisions → - Infrastructure choices for scale, cost & compliance
- Agent Configuration & Safety → - Building trustworthy agents
- Knowledge Grounding with RAG → - Ground agents in real data
- Security & Governance → - Identity, RBAC & compliance
Each guide is independent. Pick what you need.
Last updated: 2026-09-28
Questions? Explore the learning path or dive into specific topics.