LangChain + HireSquire Python SDK Tutorial: Build AI Hiring Agents
Agent Guides Featured

LangChain + HireSquire Python SDK Tutorial: Build AI Hiring Agents

HireSquire
HireSquire
· Updated May 22, 2026 · 10 min read

Complete tutorial for integrating HireSquire with LangChain. Covers Python SDK usage, @tool decorator patterns, async workflows, and LangGraph hiring pipelines.

LangChain + HireSquire Python SDK Tutorial: Build AI Hiring Agents

Learn how to integrate HireSquire's resume screening capabilities directly into your LangChain agent workflows. This tutorial covers the Python SDK, @tool decorator usage, async patterns, and LangGraph integration for autonomous hiring pipelines.

Installation
pip install hiresquire langchain langchain-openai python-dotenv

Why HireSquire + LangChain?

Integrating HireSquire with LangChain gives your AI agents native resume screening capabilities:

  • Native Python tools - First-class @tool decorator support
  • Async workflow - Non-blocking screening for agent systems
  • Structured outputs - Pydantic models for perfect agent parsing
  • LangGraph compatibility - Build stateful hiring pipelines
  • Memory integration - Track candidates across conversations

Basic SDK Usage

First, import and initialize the HireSquire client:

from hiresquire import HireSquire
import os
from dotenv import load_dotenv

load_dotenv()

# Initialize client (pass token as first positional arg)
client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))

# Submit a screening job
job = client.jobs.create(
    title="Senior Python Developer",
    description="Looking for Python developer with 5+ years experience, Django, and API design skills.",
    resumes=["./resumes/john_doe.txt", "./resumes/jane_smith.pdf"]
)

# Wait for completion
results = client.jobs.wait(job["job_id"])

# Print qualified candidates
for candidate in results["candidates"]:
    if candidate["score"] >= 80:
        print(f"✅ {candidate['name']}: {candidate['score']}/100")
        print(f"   {candidate['summary']}")

LangChain Tool Integration

Create LangChain tools using the @tool decorator for your agents:

from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate

@tool
def screen_candidates(job_title: str, job_description: str, resume_files: list[str]) -> dict:
    """
    Screen candidates against a job description using HireSquire AI.
    
    Args:
        job_title: Title of the position
        job_description: Detailed job requirements
        resume_files: List of paths to resume files
    
    Returns:
        Screening results with scores and analysis
    """
    client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))
    job = client.jobs.create(job_title, job_description, resume_files)
    return client.jobs.wait(job["job_id"])

@tool
def generate_interview_email(job_id: int, candidate_id: int) -> str:
    """
    Generate a personalized interview invitation email.
    
    Args:
        job_id: The ID of the screening job
        candidate_id: The ID of the candidate
    
    Returns:
        Formatted email content
    """
    client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))
    result = client.candidates.generate_email(
        job_id=job_id,
        candidate_id=candidate_id,
        email_type="invite",
        tone="professional"
    )
    return result["email"]["body"]

# Initialize agent
tools = [screen_candidates, generate_interview_email]
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are an AI recruiting assistant. Use the screen_candidates tool to evaluate resumes, then generate interview emails for qualified candidates (score >= 80)."),
    ("human", "{input}"),
    ("agent_scratchpad", "{agent_scratchpad}"),
])

agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Run the agent
result = executor.invoke({
    "input": "Screen these resumes for the Senior Python Developer role: ./resumes/john_doe.txt, ./resumes/jane_smith.pdf. The job requires 5+ years Python experience with Django. Send interview invites to anyone scoring 80 or higher."
})

Non-Blocking Batch Patterns

For processing multiple jobs concurrently without blocking, submit all jobs first then poll each - or use webhooks for fully event-driven workflows:

import time
from hiresquire import HireSquire

client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))

# Submit multiple jobs upfront (non-blocking)
job_python = client.jobs.create("Python Dev", python_description, python_resumes)
job_react = client.jobs.create("React Dev", react_description, react_resumes)
job_devops = client.jobs.create("DevOps", devops_description, devops_resumes)

all_job_ids = [job_python["job_id"], job_react["job_id"], job_devops["job_id"]]

# Poll all jobs until each completes
all_results = []
for job_id in all_job_ids:
    result = client.jobs.wait(job_id, poll_interval=5, timeout=300)
    all_results.append(result)

# Or configure a webhook_url when submitting to get async push notifications:
# client.screen(..., webhook_url="https://your-app.com/webhook/hiresquire")

Agent Tip: For large batches, set a webhook_url when submitting each job. HireSquire will POST results to your endpoint when complete - no polling needed, and no risk of timeout in long-running agent sessions.

LangGraph Hiring Pipeline

Build a complete stateful hiring workflow with LangGraph:

from langgraph.graph import StateGraph, END
from typing import TypedDict, List

class HiringState(TypedDict):
    job_title: str
    job_description: str
    resume_files: List[str]
    screening_results: dict
    qualified_candidates: List[dict]
    emails_sent: List[str]

def screen_resumes(state: HiringState) -> HiringState:
    client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))
    job = client.jobs.create(state["job_title"], state["job_description"], state["resume_files"])
    state["screening_results"] = client.jobs.wait(job["job_id"])
    return state

def filter_candidates(state: HiringState) -> HiringState:
    state["qualified_candidates"] = [
        c for c in state["screening_results"]["candidates"] 
        if c["score"] >= 80
    ]
    return state

def send_interviews(state: HiringState) -> HiringState:
    client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))
    state["emails_sent"] = []
    
    for candidate in state["qualified_candidates"]:
        result = client.candidates.generate_email(
            job_id=state["screening_results"]["job_id"],
            candidate_id=candidate["id"],
            email_type="invite",
            tone="professional"
        )
        # Send email via your service
        state["emails_sent"].append(candidate["name"])
    
    return state

# Build the graph
workflow = StateGraph(HiringState)
workflow.add_node("screen", screen_resumes)
workflow.add_node("filter", filter_candidates)
workflow.add_node("interview", send_interviews)

workflow.set_entry_point("screen")
workflow.add_edge("screen", "filter")
workflow.add_edge("filter", "interview")
workflow.add_edge("interview", END)

app = workflow.compile()

# Execute the pipeline
result = app.invoke({
    "job_title": "Senior Python Developer",
    "job_description": "5+ years Python, Django, API design...",
    "resume_files": ["./resumes/1.txt", "./resumes/2.txt", "./resumes/3.txt"]
})

Error Handling for Agents

Implement robust error handling for production agent systems:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def reliable_screening(title: str, description: str, resumes: list):
    try:
        client = HireSquire(api_token=os.getenv("HIRESQUIRE_API_TOKEN"))
        job = client.jobs.create(title, description, resumes)
        return client.jobs.wait(job["job_id"], timeout=300)
    except Exception as e:
        if "rate_limit" in str(e):
            raise  # Let retry handle it
        elif "invalid_token" in str(e):
            # Alert system - token needs rotation
            raise
        else:
            # Log and return partial results
            return {"error": str(e), "status": "failed"}

Handling Bad Inputs

Before passing agent inputs to the SDK, validate them to avoid API 422 errors and handle timeouts gracefully:

def safe_screen_candidates(title: str, description: str, resumes: list) -> dict:
    # 1. Validate inputs
    if not title or len(title.strip()) < 5:
        return {"error": "Validation failed: Title is too short or empty."}
        
    if not description or len(description.strip()) < 50:
        return {"error": "Validation failed: Description must be at least 50 characters."}
        
    valid_resumes = [r for r in resumes if os.path.exists(r) and os.path.getsize(r) > 0]
    if not valid_resumes:
        return {"error": "Validation failed: No valid resume files provided."}

    # 2. Execute with safety net
    try:
        client = HireSquire(os.getenv("HIRESQUIRE_API_TOKEN"))
        job = client.jobs.create(title, description, valid_resumes)
        
        # 3. Handle asynchronous timeout gracefully
        try:
            return client.jobs.wait(job["job_id"], timeout=120)
        except TimeoutError:
            return {
                "status": "processing", 
                "job_id": job["job_id"],
                "message": "Job is taking longer than expected. Continue other tasks and poll later."
            }
            
    except Exception as e:
        return {"error": f"API Error: {str(e)}", "status": "failed"}

Next Steps

Continue building your agent system with these resources:

The HireSquire Python SDK is designed from the ground up for agent integration. With native LangChain support, async operations, and structured outputs, you can build production-ready hiring agents in minutes.

Share this article:
Back to Resources
HireSquire

Written by

HireSquire

The HireSquire team is dedicated to helping entrepreneurs and hiring managers build their dream teams with AI-powered screening tools and data-driven insights.

Ready to Hire Smarter?

Start screening candidates with AI-powered insights. Get 30 free screenings, then pay less than $0.01 per candidate.

30 Free Screenings
<$0.01 /Candidate After
No Credit Card Required