Agentic applications are changing how we build software: instead of hardcoding every flow, we can create systems where an AI agent reasons, calls tools, and takes actions toward a goal. If you are a Python developer who wants to build one in a practical way, FastAPI and Azure AI Foundry are a powerful combination. FastAPI gives you a clean, high-performance API layer, while Azure AI Foundry gives you managed models, safety controls, and enterprise-ready integration. In this guide, you will build a beginner-friendly yet production-minded agentic app pattern you can adapt for support automation, internal knowledge assistants, and operational workflows.
# 1) What Is an Agentic App and Why Use FastAPI + Azure AI Foundry?
# What “agentic” means in practice
An agentic app is an application where an AI model does more than generate text. It can:
- Interpret user goals and context
- Choose actions (for example, querying a database or calling an API)
- Execute tools in sequence
- Return structured results and next steps
Think of a customer support assistant that not only answers policy questions, but also checks order status, creates tickets, and schedules callbacks by using backend tools.
# Why FastAPI?
- Speed and async support for model + tool orchestration
- Automatic OpenAPI docs for quick team onboarding
- Type safety with Pydantic for robust request/response contracts
# Why Azure AI Foundry?
- Managed access to advanced models and evaluations
- Security and governance expected in enterprise environments
- Easy integration with Azure services (Key Vault, Application Insights, AI Search)
Key takeaway: FastAPI handles your application contract and orchestration logic; Azure AI Foundry powers reasoning and model operations in a secure, scalable way.
# 2) Architecture and Local Setup (Step-by-Step)
# Reference architecture
A practical agentic app has these layers:
- API Layer (FastAPI): receives user requests and returns responses
- Agent Layer: prompt, planning logic, tool registry, memory
- Tool Layer: business APIs (CRM, ticketing, inventory, payment)
- Model Layer (Azure AI Foundry): chat/completions + safety policies
- Observability: logs, traces, metrics, prompt/version tracking
# Project structure
agentic-fastapi-app/
├── app/
│ ├── main.py
│ ├── agent.py
│ ├── tools.py
│ ├── schemas.py
│ └── config.py
├── requirements.txt
└── .env# Install dependencies
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install fastapi uvicorn python-dotenv pydantic httpx openai# Environment configuration
# .env
AZURE_OPENAI_ENDPOINT="https://YOUR-RESOURCE.openai.azure.com/"
AZURE_OPENAI_API_KEY="YOUR_API_KEY"
AZURE_OPENAI_API_VERSION="2024-02-15-preview"
AZURE_OPENAI_DEPLOYMENT="gpt-4o-mini"
# app/config.py
from pydantic import BaseModel
from dotenv import load_dotenv
import os
load_dotenv()
class Settings(BaseModel):
endpoint: str = os.getenv("AZURE_OPENAI_ENDPOINT", "")
api_key: str = os.getenv("AZURE_OPENAI_API_KEY", "")
api_version: str = os.getenv("AZURE_OPENAI_API_VERSION", "2024-02-15-preview")
deployment: str = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o-mini")
settings = Settings()# 3) Build the Core Agent with Tool Calling
# Define business tools (real-world support example)
We will simulate two tools: checking order status and creating support tickets.
# app/tools.py
from datetime import datetime
def get_order_status(order_id: str):
# In production: call ERP/OMS API
fake_db = {
"A100": {"status": "Shipped", "eta": "2026-04-24"},
"A101": {"status": "Processing", "eta": "2026-04-27"}
}
return fake_db.get(order_id, {"status": "NotFound", "eta": None})
def create_support_ticket(email: str, issue: str):
# In production: call Jira/ServiceNow/Zendesk
ticket_id = f"T-{int(datetime.utcnow().timestamp())}"
return {"ticket_id": ticket_id, "email": email, "issue": issue, "state": "Open"}# Define request/response schemas
# app/schemas.py
from pydantic import BaseModel
from typing import Optional, Dict, Any
class ChatRequest(BaseModel):
user_id: str
message: str
class ChatResponse(BaseModel):
reply: str
tool_result: Optional[Dict[str, Any]] = None# Create an agent orchestrator
# app/agent.py
from openai import AzureOpenAI
from app.config import settings
from app.tools import get_order_status, create_support_ticket
import json
client = AzureOpenAI(
api_key=settings.api_key,
azure_endpoint=settings.endpoint,
api_version=settings.api_version,
)
TOOLS = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Get order shipping status by order ID",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]
}
}
},
{
"type": "function",
"function": {
"name": "create_support_ticket",
"description": "Create support ticket for unresolved customer issue",
"parameters": {
"type": "object",
"properties": {
"email": {"type": "string"},
"issue": {"type": "string"}
},
"required": ["email", "issue"]
}
}
}
]
def run_agent(message: str):
messages = [
{"role": "system", "content": "You are a helpful support agent. Use tools when needed."},
{"role": "user", "content": message}
]
first = client.chat.completions.create(
model=settings.deployment,
messages=messages,
tools=TOOLS,
tool_choice="auto"
)
response_msg = first.choices[0].message
if not response_msg.tool_calls:
return {"reply": response_msg.content, "tool_result": None}
tool_call = response_msg.tool_calls[0]
tool_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
if tool_name == "get_order_status":
result = get_order_status(**args)
elif tool_name == "create_support_ticket":
result = create_support_ticket(**args)
else:
result = {"error": "Unknown tool"}
messages.append(response_msg)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_name,
"content": json.dumps(result)
})
second = client.chat.completions.create(
model=settings.deployment,
messages=messages
)
return {"reply": second.choices[0].message.content, "tool_result": result}# 4) Expose the Agent via FastAPI Endpoints
# Create API routes
# app/main.py
from fastapi import FastAPI, HTTPException
from app.schemas import ChatRequest, ChatResponse
from app.agent import run_agent
app = FastAPI(title="Agentic Support API")
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/chat", response_model=ChatResponse)
def chat(req: ChatRequest):
try:
result = run_agent(req.message)
return ChatResponse(**result)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))# Run and test locally
uvicorn app.main:app --reloadTry this request:
curl -X POST "http://127.0.0.1:8000/chat" \
-H "Content-Type: application/json" \
-d '{"user_id":"u1","message":"Where is order A100?"}'Expected behavior: the model chooses get_order_status, receives tool output, and replies with user-friendly status + ETA.
Tip: Keep endpoint contracts stable while iterating on agent prompts and tools internally. This makes frontend integration much easier.
# 5) Production Patterns: Memory, Safety, and Observability
# Add short-term memory
For multi-turn conversations, store recent messages (Redis, Cosmos DB, or PostgreSQL). Start simple: keep last N turns by user ID.
- Improves coherence and personalization
- Allows follow-up questions without repeating context
- Needs retention and privacy controls
# Implement guardrails and safe tool use
Agentic apps can execute actions, so safety is non-negotiable:
- Validate tool parameters with strict schemas
- Require human confirmation for destructive actions
- Use allow-lists for which tools each user role can call
- Log every tool call with user, timestamp, and payload hash
# Observability checklist
- Track latency per step (LLM call vs tool call)
- Capture token usage and cost estimates
- Store prompt/template version used in each request
- Monitor error classes (timeouts, invalid tool args, rate limits)
Warning: Most agent failures in production are orchestration issues (timeouts, bad tool outputs, stale context), not model quality alone.
# 6) Deploy to Azure and Real-World Use Cases
# Deploy FastAPI
Common options include Azure App Service, Azure Container Apps, or AKS for advanced workloads. For most teams, Container Apps offers a balanced path with autoscaling and manageable complexity.
# Integrate enterprise services
- Azure Key Vault for API keys and secrets
- Application Insights for logs and traces
- Azure AI Search for retrieval-augmented grounding
- Azure API Management for gateway policies and throttling
# Three practical use cases
- IT Helpdesk Agent: resets accounts, opens tickets, checks incident status.
- E-commerce Care Agent: order tracking, return eligibility checks, refund initiation.
- Ops Runbook Agent: fetches service health, executes safe diagnostics, drafts incident summaries.
Start with one narrow workflow and expand tool coverage after you establish quality and monitoring baselines.
# Conclusion
Building an agentic app with FastAPI and Azure AI Foundry is both accessible for beginners and robust enough for enterprise growth. The winning formula is straightforward: define clear API contracts, keep tools small and deterministic, let the model decide when to use them, and monitor everything. If you follow the architecture in this guide, you can move from a local prototype to a production-ready agent that solves real business tasks—without losing control over safety, reliability, or cost. Your next step: pick one workflow, implement two tools, and ship your first internal pilot this week.