Azure AI Foundry in 2025: Building Your First AI Agent in 30 Minutes – Part 3

Azure AI Foundry in 2025: Building Your First AI Agent in 30 Minutes – Part 3

Welcome to Part 3 of our Azure AI Foundry agent series! In Parts 1 and 2, we set up our project and built an intelligent agent in the playground. Now it’s time to write production code. In this tutorial, you’ll learn how to implement your agent using Python, Node.js, or C# with proper error handling, logging, and best practices.

By the end of this article, you’ll have production-ready code that you can deploy anywhere. Let’s transform your playground agent into professional software!

What We’re Building Today

In this tutorial, we’ll implement:

  • Local Development Setup: Create a proper project structure
  • Production Code: Write robust agent implementations in Python, Node.js, and C#
  • Error Handling: Implement retry logic and graceful failures
  • Configuration Management: Use environment variables and secure settings
  • Logging: Add comprehensive logging for debugging
  • Testing: Write tests to validate agent behavior

Step 1: Setting Up Local Development

Prerequisites

  • Python 3.9+ OR Node.js 18+ OR .NET 8+
  • Azure CLI installed
  • VS Code recommended
  • Git for version control

Project Structure

customer-support-agent/
├── .env.example
├── .gitignore
├── README.md
├── requirements.txt (Python)
├── package.json (Node.js)
├── Program.cs (C#)
└── src/
    ├── config.py/js/cs
    ├── agent.py/js/cs
    └── main.py/js/cs

Step 2: Python Implementation

Setup Python Environment

# Create project
mkdir customer-support-agent
cd customer-support-agent

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install azure-ai-projects azure-identity python-dotenv

Configuration (config.py)

import os
from dotenv import load_dotenv

load_dotenv()

class Config:
    PROJECT_ENDPOINT = os.getenv("PROJECT_ENDPOINT")
    MODEL_DEPLOYMENT_NAME = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-4o-mini")
    MAX_RETRIES = 3
    RETRY_DELAY = 2
    
    AGENT_INSTRUCTIONS = """You are a helpful customer support agent.
Always search the knowledge base before answering.
Provide accurate information with citations.
Maintain a professional, friendly tone."""
    
    @classmethod
    def validate(cls):
        if not cls.PROJECT_ENDPOINT:
            raise ValueError("PROJECT_ENDPOINT is required")

Config.validate()

Agent Implementation (agent.py)

import time
import logging
from typing import Dict, Optional
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from config import Config

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class CustomerSupportAgent:
    def __init__(self):
        self.credential = DefaultAzureCredential()
        self.client = AIProjectClient(
            endpoint=Config.PROJECT_ENDPOINT,
            credential=self.credential
        )
        self.agent_id = None
        self.thread_id = None
        logger.info("Agent initialized")
    
    def create_agent(self) -> str:
        try:
            agent = self.client.agents.create_agent(
                model=Config.MODEL_DEPLOYMENT_NAME,
                name="customer-support-agent",
                instructions=Config.AGENT_INSTRUCTIONS,
                tools=[{"type": "file_search"}]
            )
            self.agent_id = agent.id
            logger.info(f"Created agent: {self.agent_id}")
            return self.agent_id
        except Exception as e:
            logger.error(f"Error creating agent: {e}")
            raise
    
    def create_thread(self) -> str:
        try:
            thread = self.client.agents.create_thread()
            self.thread_id = thread.id
            logger.info(f"Created thread: {self.thread_id}")
            return self.thread_id
        except Exception as e:
            logger.error(f"Error creating thread: {e}")
            raise
    
    def send_message(self, message: str) -> Dict:
        if not self.thread_id:
            self.create_thread()
        
        retries = 0
        while retries < Config.MAX_RETRIES:
            try:
                # Create message
                self.client.agents.create_message(
                    thread_id=self.thread_id,
                    role="user",
                    content=message
                )
                
                # Run agent
                run = self.client.agents.create_and_process_run(
                    thread_id=self.thread_id,
                    assistant_id=self.agent_id
                )
                
                # Wait for completion
                while run.status in ["queued", "in_progress"]:
                    time.sleep(1)
                    run = self.client.agents.get_run(
                        thread_id=self.thread_id,
                        run_id=run.id
                    )
                
                if run.status == "failed":
                    raise Exception(f"Run failed: {run.last_error}")
                
                # Get response
                messages = self.client.agents.list_messages(
                    thread_id=self.thread_id
                )
                response = messages.data[0].content[0].text.value
                
                logger.info("Message processed successfully")
                return {
                    'response': response,
                    'status': 'success',
                    'thread_id': self.thread_id
                }
                
            except Exception as e:
                retries += 1
                logger.warning(f"Attempt {retries} failed: {e}")
                
                if retries >= Config.MAX_RETRIES:
                    return {
                        'response': "Error processing request",
                        'status': 'error',
                        'error': str(e)
                    }
                
                time.sleep(Config.RETRY_DELAY * retries)

Main Application (main.py)

from agent import CustomerSupportAgent

def main():
    agent = CustomerSupportAgent()
    agent.create_agent()
    agent.create_thread()
    
    print("Customer Support Agent Ready!")
    print("Type 'quit' to exit\n")
    
    while True:
        user_input = input("You: ")
        
        if user_input.lower() == 'quit':
            break
        
        result = agent.send_message(user_input)
        
        if result['status'] == 'success':
            print(f"\nAgent: {result['response']}\n")
        else:
            print(f"\nError: {result.get('error')}\n")

if __name__ == "__main__":
    main()

Environment File (.env)

PROJECT_ENDPOINT=https://your-resource.services.ai.azure.com/api/projects/your-project
MODEL_DEPLOYMENT_NAME=gpt-4o-mini

Step 3: Node.js Implementation

Setup Node.js Project

# Initialize project
npm init -y

# Install dependencies
npm install @azure/ai-projects @azure/identity dotenv

Configuration (config.js)

require('dotenv').config();

class Config {
    static PROJECT_ENDPOINT = process.env.PROJECT_ENDPOINT;
    static MODEL_DEPLOYMENT_NAME = process.env.MODEL_DEPLOYMENT_NAME || 'gpt-4o-mini';
    static MAX_RETRIES = 3;
    static RETRY_DELAY = 2000;
    
    static AGENT_INSTRUCTIONS = `You are a helpful customer support agent.
Always search the knowledge base before answering.
Provide accurate information with citations.
Maintain a professional, friendly tone.`;
    
    static validate() {
        if (!this.PROJECT_ENDPOINT) {
            throw new Error('PROJECT_ENDPOINT is required');
        }
    }
}

Config.validate();

module.exports = Config;

Agent Implementation (agent.js)

const { AIProjectClient } = require('@azure/ai-projects');
const { DefaultAzureCredential } = require('@azure/identity');
const Config = require('./config');

class CustomerSupportAgent {
    constructor() {
        this.credential = new DefaultAzureCredential();
        this.client = new AIProjectClient(
            Config.PROJECT_ENDPOINT,
            this.credential
        );
        this.agentId = null;
        this.threadId = null;
    }
    
    async createAgent() {
        try {
            const agent = await this.client.agents.createAgent({
                model: Config.MODEL_DEPLOYMENT_NAME,
                name: 'customer-support-agent',
                instructions: Config.AGENT_INSTRUCTIONS,
                tools: [{ type: 'file_search' }]
            });
            
            this.agentId = agent.id;
            console.log(`Created agent: ${this.agentId}`);
            return this.agentId;
        } catch (error) {
            console.error('Error creating agent:', error);
            throw error;
        }
    }
    
    async createThread() {
        try {
            const thread = await this.client.agents.createThread();
            this.threadId = thread.id;
            console.log(`Created thread: ${this.threadId}`);
            return this.threadId;
        } catch (error) {
            console.error('Error creating thread:', error);
            throw error;
        }
    }
    
    async sendMessage(message) {
        if (!this.threadId) {
            await this.createThread();
        }
        
        let retries = 0;
        
        while (retries < Config.MAX_RETRIES) {
            try {
                // Create message
                await this.client.agents.createMessage(
                    this.threadId,
                    { role: 'user', content: message }
                );
                
                // Run agent
                let run = await this.client.agents.createRun(
                    this.threadId,
                    { assistantId: this.agentId }
                );
                
                // Wait for completion
                while (['queued', 'in_progress'].includes(run.status)) {
                    await new Promise(resolve => setTimeout(resolve, 1000));
                    run = await this.client.agents.getRun(this.threadId, run.id);
                }
                
                if (run.status === 'failed') {
                    throw new Error(`Run failed: ${run.lastError}`);
                }
                
                // Get response
                const messages = await this.client.agents.listMessages(this.threadId);
                const response = messages.data[0].content[0].text.value;
                
                return {
                    response,
                    status: 'success',
                    threadId: this.threadId
                };
                
            } catch (error) {
                retries++;
                console.warn(`Attempt ${retries} failed:`, error.message);
                
                if (retries >= Config.MAX_RETRIES) {
                    return {
                        response: 'Error processing request',
                        status: 'error',
                        error: error.message
                    };
                }
                
                await new Promise(resolve => 
                    setTimeout(resolve, Config.RETRY_DELAY * retries)
                );
            }
        }
    }
}

module.exports = CustomerSupportAgent;

Main Application (main.js)

const readline = require('readline');
const CustomerSupportAgent = require('./agent');

async function main() {
    const agent = new CustomerSupportAgent();
    await agent.createAgent();
    await agent.createThread();
    
    console.log('Customer Support Agent Ready!');
    console.log("Type 'quit' to exit\n");
    
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });
    
    const askQuestion = () => {
        rl.question('You: ', async (input) => {
            if (input.toLowerCase() === 'quit') {
                rl.close();
                return;
            }
            
            const result = await agent.sendMessage(input);
            
            if (result.status === 'success') {
                console.log(`\nAgent: ${result.response}\n`);
            } else {
                console.log(`\nError: ${result.error}\n`);
            }
            
            askQuestion();
        });
    };
    
    askQuestion();
}

main().catch(console.error);

Step 4: C# Implementation

Setup C# Project

# Create project
dotnet new console -n CustomerSupportAgent
cd CustomerSupportAgent

# Add packages
dotnet add package Azure.AI.Projects --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables

Configuration (appsettings.json)

{
  "Azure": {
    "ProjectEndpoint": "",
    "ModelDeploymentName": "gpt-4o-mini"
  },
  "Agent": {
    "MaxRetries": 3,
    "RetryDelaySeconds": 2
  }
}

Agent Implementation (Program.cs)

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddEnvironmentVariables()
    .Build();

var projectEndpoint = configuration["Azure:ProjectEndpoint"];
var modelName = configuration["Azure:ModelDeploymentName"];

var credential = new DefaultAzureCredential();
var client = new AIProjectClient(new Uri(projectEndpoint), credential);

Console.WriteLine("Creating agent...");

var agent = await client.Agents.CreateAgentAsync(
    model: modelName,
    name: "customer-support-agent",
    instructions: @"You are a helpful customer support agent.
Always search the knowledge base before answering.
Provide accurate information with citations.
Maintain a professional, friendly tone.",
    tools: new[] { new FileSearchToolDefinition() }
);

Console.WriteLine($"Agent created: {agent.Value.Id}");

var thread = await client.Agents.CreateThreadAsync();
Console.WriteLine($"Thread created: {thread.Value.Id}");

Console.WriteLine("\nCustomer Support Agent Ready!");
Console.WriteLine("Type 'quit' to exit\n");

while (true)
{
    Console.Write("You: ");
    var input = Console.ReadLine();
    
    if (input?.ToLower() == "quit")
        break;
    
    try
    {
        await client.Agents.CreateMessageAsync(
            thread.Value.Id,
            MessageRole.User,
            input
        );
        
        var run = await client.Agents.CreateRunAsync(
            thread.Value.Id,
            agent.Value.Id
        );
        
        while (run.Value.Status == RunStatus.Queued || 
               run.Value.Status == RunStatus.InProgress)
        {
            await Task.Delay(1000);
            run = await client.Agents.GetRunAsync(thread.Value.Id, run.Value.Id);
        }
        
        if (run.Value.Status == RunStatus.Failed)
        {
            Console.WriteLine($"\nError: {run.Value.LastError}\n");
            continue;
        }
        
        var messages = await client.Agents.GetMessagesAsync(thread.Value.Id);
        var response = messages.Value.Data[0].Content[0].Text.Value;
        
        Console.WriteLine($"\nAgent: {response}\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"\nError: {ex.Message}\n");
    }
}

Step 5: Running Your Agent Locally

Python

# Authenticate with Azure
az login

# Run the agent
python src/main.py

Node.js

# Authenticate with Azure
az login

# Run the agent
node src/main.js

C#

# Authenticate with Azure
az login

# Run the agent
dotnet run

Step 6: Testing Your Agent

Test your agent with these queries:

You: What is your return policy?
Agent: [Response with citation from knowledge base]

You: How long does shipping take?
Agent: [Response with shipping information]

You: Can I change my subscription?
Agent: [Response about subscription changes]

Common Issues and Solutions

Authentication Errors:

# Ensure you're logged in to Azure
az login

# Check your account
az account show

Missing Environment Variables:

Verify your .env file contains the correct PROJECT_ENDPOINT from Azure AI Foundry portal.

Agent Not Finding Information:

Ensure you uploaded files to the vector store in Part 2 and the agent has access to the File Search tool.

Key Concepts Recap

  • Configuration Management: Use environment variables for sensitive data
  • Error Handling: Implement retry logic for network failures
  • Logging: Add comprehensive logging for debugging
  • DefaultAzureCredential: Use managed authentication instead of API keys
  • Async/Await: Handle asynchronous operations properly
  • Thread Management: Maintain conversation context across messages

What’s Next in Part 4?

In the final part of this series, we’ll cover deployment and advanced topics:

  • Containerizing your application with Docker
  • Deploying to Azure Container Apps
  • Setting up CI/CD with GitHub Actions
  • Implementing monitoring with Application Insights
  • Security best practices and managed identities
  • Cost optimization strategies
  • Performance tuning and scaling

We’ll take your local agent and deploy it to production.


References

This article is Part 3 of a 4-part series on building AI agents with Azure AI Foundry in 2025.

Written by:

373 Posts

View All Posts
Follow Me :
How to whitelist website on AdBlocker?

How to whitelist website on AdBlocker?

  1. 1 Click on the AdBlock Plus icon on the top right corner of your browser
  2. 2 Click on "Enabled on this site" from the AdBlock Plus option
  3. 3 Refresh the page and start browsing the site