DEV Community

Cover image for Building a Multi-Agent Candidate Search System with Azure AI Foundry
Seenivasa Ramadurai
Seenivasa Ramadurai

Posted on

Building a Multi-Agent Candidate Search System with Azure AI Foundry

Introduction

In today's competitive hiring landscape, recruiters and HR professionals need powerful tools to quickly gather comprehensive information about potential candidates. Traditional search methods are time-consuming and often miss crucial details scattered across different platforms.

This blog post explores how we built a sophisticated Multi-Agent Candidate Search System that leverages the power of Azure AI Foundry, real-time web search APIs, and modern web technologies to create a comprehensive candidate research platform.

Note: This demo application is designed to showcase how to build and manage multi-agent systems in Azure AI Foundry. Some API keys and configuration values are hardcoded for demonstration purposes only in a production setup, these should be securely stored in Azure Key Vault (or another secure location) and accessed by the AI agents at runtime.

The Challenge: Information Scattered Everywhere

When researching a candidate, information is typically scattered across:

LinkedIn for professional experience and skills
Web searches for news, publications, and achievements
Social media for personal insights and engagement
Professional networks for endorsements and connections

Manually searching each platform is inefficient and prone to missing important details. Our solution? AI-powered agents that work together to gather and analyze information comprehensively.

What is Multi-Agent Architecture?

Multi-Agent Architecture is a design pattern where multiple specialized AI agents work together to solve complex problems. Think of it like having a team of expert consultants, each with their own specialty, collaborating on a project.

Traditional vs Multi-Agent Approach

Traditional Single Agent:

  1. One AI tries to do everything
  2. Limited by its general knowledge
  3. Can miss specialized details
  4. Slower and less accurate

Multi-Agent System:

  1. Multiple specialized AI agents
  2. Each agent is an expert in their domain
  3. Agents collaborate and share information
  4. Faster, more accurate, and comprehensive

High-Level AI Agents System Overview

Detailed Agent Communication Flow

Agent Specialization and Roles

Understanding the Key Components

1. Azure AI Foundry AgentsClient

The AgentsClient is your gateway to Azure AI Foundry's powerful agent management system. Think of it as the "conductor" of an orchestra - it coordinates all the different AI agents and manages their interactions.

What it does:

Creates and manages AI agents with specific roles and capabilities
Handles agent communication and coordination
Manages conversation threads between agents and users
Provides access to GPT-4o and other advanced AI models
In simple terms: It's like having a smart project manager that knows how to assign tasks to the right AI specialists and coordinate their work.

2. ConnectedAgentTool

ConnectedAgentTool is the mechanism that allows agents to "talk" to each other. It's like giving each agent a direct phone line to other specialized agents.

How it works:

Agent A (LinkedIn specialist) can call Agent B (Web researcher) for additional information
Agent C (Analysis coordinator) can gather results from all other agents
Seamless communication between different AI specialists
Real-world analogy: Imagine you're organizing a research project. Each team member has a specific expertise, and they can call each other directly to share information and collaborate.

3. MessageRole and Thread Management

The system uses conversation threads to maintain context and organize communication:

MessageRole.USER: Messages from the human user
MessageRole.AGENT: Responses from AI agents
Threads: Organized conversations that maintain context
Why this matters: Just like in human conversations, context is crucial. The system remembers what was discussed earlier in the conversation, leading to more relevant and coherent responses.

NOTE : For how to Create an Azure AI Foundry project, please refer the following blog of mine https://dev.to/sreeni5018/building-an-intelligent-rag-agent-with-azure-ai-foundry-a-deep-dive-into-sreeni-rag-252b

"""
FastAPI Backend for Multi-Agent Candidate Search System
======================================================

This FastAPI application exposes the multi-agent candidate search system as a REST API.
It provides endpoints for searching candidate information using Azure AI Foundry agents
and Tavily API integration.

Author: Sreeni Ramadurai
Date: 2025 OCT 5
"""

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Dict, Any
import os
import sys
import requests
from dotenv import load_dotenv
import asyncio
import uvicorn

# Azure AI Foundry imports for agent management
from azure.ai.agents import AgentsClient
from azure.ai.agents.models import ConnectedAgentTool, MessageRole, ListSortOrder, ToolSet, FunctionTool
from azure.identity import DefaultAzureCredential

# Load environment variables
load_dotenv()
project_endpoint = os.getenv("PROJECT_ENDPOINT")
model_deployment = os.getenv("MODEL_DEPLOYMENT_NAME")

# Initialize FastAPI app
app = FastAPI(
    title="Multi-Agent Candidate Search API",
    description="API for searching candidate information using Azure AI Foundry agents and Tavily API",
    version="1.0.0"
)

# Request/Response models
class CandidateSearchRequest(BaseModel):
    candidate_name: str

class CandidateSearchResponse(BaseModel):
    candidate_name: str
    linkedin_results: str
    web_results: str
    social_results: str
    analysis: str
    status: str

def search_tavily(query: str, search_type: str = "general") -> str:
    """
    Search using Tavily API for real-time web data retrieval

    Args:
        query (str): The search query (candidate name)
        search_type (str): Type of search - "linkedin", "social", or "general"

    Returns:
        str: Formatted search results or error message
    """
    try:
        # Tavily API endpoint and authentication
        url = "https://api.tavily.com/search"
        headers = {"Authorization": "Bearer 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"}

        # Build more specific search query based on search type
        if search_type == "linkedin":
            search_query = f'"{query}" site:linkedin.com/in/ OR site:linkedin.com/pub/'
        elif search_type == "social":
            search_query = f'"{query}" (site:twitter.com OR site:facebook.com OR site:instagram.com)'
        else:
            search_query = f'"{query}" (profile OR biography OR "about" OR "background")'

        # API request payload
        data = {
            "query": search_query,
            "search_depth": "advanced",
            "max_results": 5
        }

        # Make API call
        response = requests.post(url, headers=headers, json=data)

        if response.status_code == 200:
            results = response.json()
            search_results = results.get('results', [])

            # Filter and format results for better quality
            filtered_results = []
            query_lower = query.lower()

            for result in search_results:
                title = result.get('title', '')
                content = result.get('content', '')
                url = result.get('url', '')

                # Filter out results that don't seem to be about the specific person
                if (query_lower in title.lower() or 
                    query_lower in content.lower() or 
                    any(word in content.lower() for word in query_lower.split())):

                    # Clean up the content
                    clean_content = content[:300] + "..." if len(content) > 300 else content
                    clean_content = clean_content.replace('\n', ' ').replace('\r', ' ')

                    filtered_results.append({
                        "title": title,
                        "url": url,
                        "content": clean_content
                    })

            # Limit to top 3 results for better quality
            top_results = filtered_results[:3]

            if not top_results:
                return f"No specific results found for '{query}' in {search_type} search."

            formatted_output = f"Search Results for '{query}' ({search_type}):\n\n"
            for i, result in enumerate(top_results, 1):
                formatted_output += f"{i}. {result['title']}\n"
                formatted_output += f"   {result['content']}\n"
                formatted_output += f"   Source: {result['url']}\n\n"

            return formatted_output
        else:
            return f"Search failed with status {response.status_code}: {response.text}"
    except Exception as e:
        return f"Search error: {str(e)}"

async def perform_candidate_search(candidate_name: str) -> Dict[str, Any]:
    """
    Perform comprehensive candidate search using multiple specialized agents

    Args:
        candidate_name (str): The name of the candidate to search for

    Returns:
        Dict[str, Any]: Dictionary containing search results and analysis
    """
    try:
        # Initialize Azure AI Foundry Agents Client
        agents_client = AgentsClient(
            endpoint=project_endpoint,
            credential=DefaultAzureCredential(
                exclude_environment_credential=True, 
                exclude_managed_identity_credential=True
            ),
        )

        with agents_client:
            # Create individual specialized agents for candidate search

            # Agent 1: LinkedIn Search Specialist
            linkedin_agent_name = "linkedin_agent"
            linkedin_agent_instructions = f"""
            You are a LinkedIn search specialist. When given a candidate name, you will:

            1. Search LinkedIn for professional information about the candidate using Tavily API
            2. Find and provide:
               - Professional profile information
               - Work experience and career history
               - Education background
               - Skills and endorsements
               - Professional connections and network

            IMPORTANT: Use this exact API call to search LinkedIn:
            POST https://api.tavily.com/search
            Headers: {{"Authorization": "Bearer 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"}}
            Body: {{"query": "{{candidate_name}} site:linkedin.com", "search_depth": "advanced", "max_results": 5}}

            Make the actual API call and respond with a summary of the LinkedIn findings from the search results.
            """
            linkedin_agent = agents_client.create_agent(
                model=model_deployment,
                name=linkedin_agent_name,
                instructions=linkedin_agent_instructions
            )

            # Agent 2: Web Research Specialist
            web_agent_name = "web_agent"
            web_agent_instructions = f"""
            You are a web research specialist. When given a candidate name, you will:

            1. Search the general web for comprehensive information about the candidate using Tavily API
            2. Find and provide:
               - Professional websites and portfolios
               - News articles and press coverage
               - Publications and research
               - Company profiles and achievements
               - Professional accomplishments and awards

            IMPORTANT: Use this exact API call to search the web:
            POST https://api.tavily.com/search
            Headers: {{"Authorization": "Bearer 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"}}
            Body: {{"query": "{{candidate_name}} professional profile biography", "search_depth": "advanced", "max_results": 5}}

            Make the actual API call and respond with a summary of the web search findings from the search results.
            """
            web_agent = agents_client.create_agent(
                model=model_deployment,
                name=web_agent_name,
                instructions=web_agent_instructions
            )

            # Agent 3: Social Media Analyst
            social_agent_name = "social_agent"
            social_agent_instructions = f"""
            You are a social media analyst. When given a candidate name, you will:

            1. Search social media platforms for information about the candidate using Tavily API
            2. Find and provide:
               - Personal profiles on Facebook, Twitter, Instagram
               - Social media activity and posts
               - Public interactions and engagement
               - Social connections and networks
               - Personal interests and activities

            IMPORTANT: Use this exact API call to search social media:
            POST https://api.tavily.com/search
            Headers: {{"Authorization": "Bearer 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"}}
            Body: {{"query": "{{candidate_name}} site:twitter.com OR site:facebook.com OR site:instagram.com", "search_depth": "advanced", "max_results": 5}}

            Make the actual API call and respond with a summary of the social media findings from the search results.
            """
            social_agent = agents_client.create_agent(
                model=model_deployment,
                name=social_agent_name,
                instructions=social_agent_instructions
            )

            # Create connected agent tools for the search agents
            linkedin_agent_tool = ConnectedAgentTool(
                id=linkedin_agent.id, 
                name=linkedin_agent_name, 
                description="Search LinkedIn for professional candidate information"
            )

            web_agent_tool = ConnectedAgentTool(
                id=web_agent.id, 
                name=web_agent_name, 
                description="Search the general web for candidate information"
            )

            social_agent_tool = ConnectedAgentTool(
                id=social_agent.id, 
                name=social_agent_name, 
                description="Search social media platforms for candidate information"
            )

            # Create the main coordinator agent with connected tools
            candidate_search_agent_name = "candidate-search-agent"
            candidate_search_agent_instructions = """
            Search for comprehensive information about the given candidate. Use the connected tools to determine the candidate's LinkedIn profile, web presence, and social media activity.
            """

            candidate_search_agent = agents_client.create_agent(
                model=model_deployment,
                name=candidate_search_agent_name,
                instructions=candidate_search_agent_instructions,
                tools=[
                    linkedin_agent_tool.definitions[0],
                    web_agent_tool.definitions[0],
                    social_agent_tool.definitions[0]
                ]
            )

            # Perform actual Tavily API searches first
            linkedin_results = search_tavily(candidate_name, "linkedin")
            web_results = search_tavily(candidate_name, "general")
            social_results = search_tavily(candidate_name, "social")

            # Create agent thread and send search results for analysis
            thread = agents_client.threads.create()

            search_summary = f"""
            Please analyze the following search results for candidate: {candidate_name}

            IMPORTANT: Focus ONLY on information that clearly relates to {candidate_name}. Ignore any results that might be about different people with similar names.

            LINKEDIN SEARCH RESULTS:
            {linkedin_results}

            WEB SEARCH RESULTS:
            {web_results}

            SOCIAL MEDIA SEARCH RESULTS:
            {social_results}

            Create a comprehensive candidate profile with the following structure:

            **Professional Background:**
            - Current role and company
            - Key skills and expertise
            - Career progression

            **Education & Certifications:**
            - Educational background
            - Professional certifications
            - Relevant training

            **Publications & Thought Leadership:**
            - Articles, papers, or publications
            - Speaking engagements
            - Industry recognition

            **Social Media Presence:**
            - Professional social media activity
            - Key interests and topics
            - Engagement and influence

            **Key Insights:**
            - Notable achievements
            - Unique qualifications
            - Potential cultural fit indicators

            **Summary & Recommendations:**
            - Overall assessment
            - Strengths and areas of expertise
            - Recommendation for next steps

            Format the response with clear sections and bullet points. Only include information that is clearly about {candidate_name}.
            """

            message = agents_client.messages.create(
                thread_id=thread.id,
                role=MessageRole.USER,
                content=search_summary,
            )

            # Run the analysis
            run = agents_client.runs.create_and_process(thread_id=thread.id, agent_id=candidate_search_agent.id)

            # Get the analysis results
            analysis = ""
            if run.status != "failed":
                messages = agents_client.messages.list(thread_id=thread.id, order=ListSortOrder.ASCENDING)
                for message in messages:
                    if message.text_messages:
                        last_msg = message.text_messages[-1]
                        analysis = last_msg.text.value
            else:
                analysis = f"Analysis failed: {run.last_error}"

            # Clean up agents
            agents_client.delete_agent(candidate_search_agent.id)
            agents_client.delete_agent(linkedin_agent.id)
            agents_client.delete_agent(web_agent.id)
            agents_client.delete_agent(social_agent.id)

            return {
                "candidate_name": candidate_name,
                "linkedin_results": linkedin_results,
                "web_results": web_results,
                "social_results": social_results,
                "analysis": analysis,
                "status": "success"
            }

    except Exception as e:
        return {
            "candidate_name": candidate_name,
            "linkedin_results": "",
            "web_results": "",
            "social_results": "",
            "analysis": f"Error: {str(e)}",
            "status": "error"
        }

@app.get("/")
async def root():
    """Root endpoint with API information"""
    return {
        "message": "Multi-Agent Candidate Search API",
        "version": "1.0.0",
        "endpoints": {
            "search": "/search",
            "health": "/health"
        }
    }

@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "candidate-search-api"}

@app.post("/search", response_model=CandidateSearchResponse)
async def search_candidate(request: CandidateSearchRequest):
    """
    Search for candidate information using multi-agent system

    Args:
        request (CandidateSearchRequest): The candidate search request

    Returns:
        CandidateSearchResponse: Comprehensive candidate information
    """
    try:
        if not request.candidate_name.strip():
            raise HTTPException(status_code=400, detail="Candidate name cannot be empty")

        # Perform the candidate search
        result = await perform_candidate_search(request.candidate_name.strip())

        return CandidateSearchResponse(**result)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Search failed: {str(e)}")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)


Enter fullscreen mode Exit fullscreen mode

Conclusion

The Multi-Agent Candidate Search System represents a significant advancement in recruitment technology. By combining the power of Azure AI Foundry's agent capabilities with real-time web search APIs and modern web technologies, we've created a solution that:

  1. Saves time for recruiters and HR professionals
  2. Provides comprehensive insights about candidates
  3. Maintains high quality through AI-powered analysis
  4. Scales effectively for enterprise use
  5. The system demonstrates how modern AI technologies can be combined to solve real-world business challenges, creating value for organizations and improving the hiring process for everyone involved.

Key Takeaways

  1. Multi-agent architecture enables specialized, parallel processing
  2. Azure AI Foundry provides powerful agent management capabilities
  3. Real-time APIs ensure current, relevant information
  4. Modern web technologies create engaging user experiences
  5. AI analysis adds valuable insights to raw data

The future of recruitment technology lies in intelligent automation that enhances human decision-making rather than replacing it. Our Multi-Agent Candidate Search System is a step toward that future.

Test the Agent & Output

User Interface -Streamlit

Searching Information about Seenivasa Ramadurai

Thanks
Sreeni Ramadorai

Top comments (0)