┌─────────────────────────────────────────────────────┐
│ Your Application │
│ (Python / .NET SDK Client) │
└──────────────────────┬──────────────────────────────┘
│ HTTPS/REST
┌──────────────────────▼──────────────────────────────┐
│ Azure AI Foundry Project │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Agent 1 │ │ Agent 2 │ │ Connections │ │
│ │ (GPT-4o) │ │ (GPT-4o) │ │ - AI Search │ │
│ │ + Tools │ │ + Tools │ │ - Storage │ │
│ └────┬─────┘ └────┬─────┘ │ - Custom APIs │ │
│ │ │ └───────────────────┘ │
│ ┌────▼─────────────▼────────────────────────────┐ │
│ │ Agent Runtime │ │
│ │ ┌─────────┐ ┌───────────┐ ┌──────────────┐ │ │
│ │ │ Threads │ │ Runs │ │ Tool Executor│ │ │
│ │ │ & Msgs │ │ & Polling │ │ │ │ │
│ │ └─────────┘ └───────────┘ └──────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────────┐┌──────────────┐┌──────────────┐
│ Code ││ Azure AI ││ External │
│ Interpreter ││ Search ││ APIs │
│ ││ (RAG) ││ (OpenAPI) │
└──────────────┘└──────────────┘└──────────────┘
The SDK follows a layered client pattern:
AIProjectClient (top-level client)
├── .agents (agents namespace / sub-client)
│ ├── create_agent() → Agent
│ ├── create_thread() → Thread
│ ├── create_message() → Message
│ ├── create_run() → Run
│ ├── create_and_process_run() → Run (with automatic polling)
│ └── create_stream() → Stream
└── .connections / .telemetry (other sub-clients)
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
# Top-level client
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str="<connection-string>"
)
# Access the agents sub-client
agents_client = project_client.agents
var projectClient = new AIProjectClient(connectionString, new DefaultAzureCredential());
// Access the agents sub-client
AgentsClient agentsClient = projectClient.GetAgentsClient();
Threads are lightweight conversation containers:
Thread
├── Message 1 (role: user) "Analyze this CSV file"
├── Message 2 (role: assistant) "I'll analyze the data..."
├── Message 3 (role: user) "Show me a chart"
└── Message 4 (role: assistant) "Here's the visualization..." + [image file]
A run progresses through states:
┌──────────────────────────────────┐
│ │
create_run() → queued → in_progress ──→ completed │
│ │
├──→ requires_action ────┘
│ (function calls) submit_tool_outputs()
│
├──→ failed
└──→ cancelled
Polling approach (create_and_process_run):
Manual polling:
create_run() then poll get_run() in a loopStreaming approach (create_stream):
When an agent decides to use a tool:
1. Agent receives thread context
2. Agent decides a tool call is needed
3. Run enters "requires_action" state (for function calling)
— or tool executes server-side (code interpreter, file search)
4. For function calling:
a. Your code receives the function name + arguments
b. Your code executes the function
c. Your code submits the result via submit_tool_outputs()
d. Run resumes processing
5. Agent incorporates tool results into its response
6. Run reaches "completed" state
┌─────────────────────────────────────────────────────────────┐
│ Azure Cloud │
│ │
│ ┌───────────────┐ ┌──────────────────────────────────┐ │
│ │ Azure Front │ │ VNet │ │
│ │ Door / APIM │───▶│ ┌────────────────────────────┐ │ │
│ └───────────────┘ │ │ App Service / Container │ │ │
│ │ │ Apps (your application) │ │ │
│ │ │ + Managed Identity │ │ │
│ │ └──────────┬─────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────▼─────────────────┐ │ │
│ │ │ AI Foundry Project │ │ │
│ │ │ (Private Endpoint) │ │ │
│ │ └────────────────────────────┘ │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ App Insights │ │ Key Vault │ │ Azure AI Search │ │
│ │ (monitoring) │ │ (secrets) │ │ (knowledge base) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
In production, use Managed Identity — no secrets to manage or rotate.
# In production, DefaultAzureCredential picks up Managed Identity automatically
credential = DefaultAzureCredential()
project_client = AIProjectClient.from_connection_string(
credential=credential,
conn_str=os.environ["AZURE_AI_CONNECTION_STRING"]
)
Assign the required RBAC role to the managed identity:
az role assignment create \
--assignee <managed-identity-principal-id> \
--role "Azure AI User" \
--scope <ai-foundry-project-resource-id>
Integrate Application Insights for observability:
from azure.monitor.opentelemetry import configure_azure_monitor
configure_azure_monitor(connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"])
Store sensitive configuration in Azure Key Vault:
Place an API gateway in front of your application for:
Automate deployment with Azure DevOps or GitHub Actions:
Code Push → Build → Test → Deploy Infrastructure (Bicep/Terraform) → Deploy Application
Key stages: