Agent Memory for HR & Recruitment
The Problem: Why Stateless Recruitment Fails
Traditional recruitment AI systems treat each candidate interaction as isolated. When recruiting across weeks or months:
- Repeated interviews: Candidate is asked "Tell us about your background" in round 1, same question in round 2 by different agent, feels dismissive
- Lost candidate context: Agent doesn't recall candidate mentioned "I'm an iOS expert with 8 years experience", evaluates them as junior web developer
- Inconsistent scoring: Candidate scores 7/10 after round 1, agent re-evaluates after round 2 and scores 4/10 (no memory of prior assessment)
- Dropped candidates: High-performing candidate from 2 weeks ago is forgotten, similar role opens, agent doesn't resurface them
- Missed offer history: Agent doesn't know candidate already rejected a 155k, candidate declines again
- Role mismatch: Agent doesn't recall role requires "lead-time management experience", recommends candidates without it
Result: Slow hiring, candidate frustration, repeated feedback loops, missed opportunities, and poor hire quality.
Agent memory solves this by storing candidate profiles, interview feedback, role specs, and offer history—enabling faster, more consistent hiring decisions.
Memory Types for HR & Recruitment
A recruitment AI agent needs four types of memory:
| Type | Content | Example | Retrieval |
|---|---|---|---|
| Candidate Facts | Resume, skills, experience, location, salary expectations | "Alice Chen: iOS engineer, 8 yrs, San Francisco, $180k target, visa sponsorship needed" | Keyword (skill, location) + semantic |
| Interview Feedback | Notes from each round, scores, strengths, weaknesses, red flags | "Round 1: Strong architecture discussion, weak on mobile performance optimization. Score: 7/10" | Temporal (round-by-round) + semantic |
| Role Requirements | Job description, required skills, nice-to-haves, must-haves | "React + Node.js required, GraphQL preferred, team lead experience required" | Keyword (skill) |
| Offer History | Offers made, compensation, status (accepted/rejected/pending) | "Offer 1: 180k (pending)" | Temporal (most-recent-first) |
Retrieval Pattern: "Active Candidates + Role Requirements + Interview Notes"
When screening a new candidate or updating their status, retrieve in order:
1. Candidate facts (keyword + semantic)
→ Recruiter knows background, skills, expectations, location/visa needs
2. Role requirements (keyword)
→ Agent checks skills match against role musts/nice-to-haves
3. Interview feedback (temporal)
→ Agent knows assessments from all rounds, strengths, development areas
4. Offer history (temporal)
→ Agent knows what was offered, why rejected, current compensation expectationsExample:
import { Brain } from "brain-ai";
const memory = new Brain({
namespace: "hr-recruitment",
});
// When evaluating a candidate or advancing them:
async function evaluateCandidate(candidateId: string, roleId: string, action: "screen" | "interview" | "offer" | "extend") {
// 1. Get candidate facts
const candidateFacts = await memory.retrieve({
agentId: `candidate-${candidateId}`,
query: "background skills experience location salary expectations visa",
topK: 5,
filters: { type: "candidate_fact" },
});
// 2. Get role requirements
const roleReqs = await memory.retrieve({
agentId: `role-${roleId}`,
query: "required skills nice-to-haves must-haves experience level team structure",
topK: 8,
filters: { type: "role_requirement" },
});
// 3. Get interview feedback
const interviewFeedback = await memory.retrieve({
agentId: `candidate-${candidateId}`,
query: "interview feedback assessment scores strengths weaknesses red flags",
topK: 10,
filters: { type: "interview_feedback" },
});
// 4. Get offer history
const offerHistory = await memory.retrieve({
agentId: `candidate-${candidateId}`,
query: "offers made compensation status accepted rejected",
topK: 5,
filters: { type: "offer_history" },
});
// Build hiring context
const hiringContext = {
candidateFacts,
roleRequirements: roleReqs,
interviewFeedback,
offerHistory,
proposedAction: action,
};
// Agent evaluates candidate fit and next step
const decision = await recruitingEngine.evaluate(hiringContext);
// Store feedback or decision
if (action === "interview") {
await memory.store({
agentId: `candidate-${candidateId}`,
content: `Round ${decision.roundNumber} feedback: ${decision.feedbackSummary}`,
type: "interview_feedback",
metadata: {
candidateId,
roleId,
timestamp: new Date().toISOString(),
roundNumber: decision.roundNumber,
interviewer: decision.interviewerName,
score: decision.score,
strengths: decision.strengths,
weaknesses: decision.weaknesses,
recommendation: decision.recommendation,
},
});
} else if (action === "offer") {
await memory.store({
agentId: `candidate-${candidateId}`,
content: `Offer made: $${decision.salary}k + benefits package`,
type: "offer_history",
metadata: {
candidateId,
roleId,
timestamp: new Date().toISOString(),
salary: decision.salary,
offeredDate: new Date().toISOString(),
status: "pending",
benefits: decision.benefits,
},
});
}
return decision;
}
// When adding a new candidate:
async function ingestCandidate(candidateId: string, resume: string, sourceChannel: string) {
const parsed = await parseResume(resume);
await memory.store({
agentId: `candidate-${candidateId}`,
content: `Resume: ${parsed.summary}`,
type: "candidate_fact",
metadata: {
candidateId,
timestamp: new Date().toISOString(),
sourceChannel,
name: parsed.name,
email: parsed.email,
phone: parsed.phone,
skills: parsed.skills,
yearsOfExperience: parsed.yearsOfExperience,
location: parsed.location,
salaryExpectation: parsed.salaryExpectation,
visaStatus: parsed.visaStatus,
},
});
}Example: Recruitment Agent Remembers
Candidate moves through hiring pipeline over 3 weeks:
Candidate: Alice Chen, iOS Engineer
Week 1 - Initial Screen:
AI Memory Lookup:
1. Candidate facts:
- Name: Alice Chen, San Francisco
- Skills: iOS (Swift), backend (Kotlin/Java), 8 yrs experience
- Salary expectation: $170k-$190k
- Visa: US citizen, no sponsorship needed
- Strengths: Architecture, mobile performance, team mentoring
2. Role requirements (for iOS/Backend Lead):
- Must-have: 5+ yrs iOS, React Native or native mobile, REST APIs
- Must-have: Team lead experience or mentoring
- Nice-to-have: GraphQL, CI/CD pipeline setup
- Salary range: $160k-$200k
3. Interview feedback: None yet (first contact)
4. Offer history: None yet
AI Recommendation: "Strong match on musts (8 yrs iOS > 5yr requirement, has mentoring). No nice-to-haves, but not blockers. Offer first-round technical screen."
---
Week 2 - After Round 1 Technical Screen:
AI Memory Lookup:
1. Candidate facts: (same as above, plus notes from conversation)
2. Role requirements: (same as above)
3. Interview feedback:
- Round 1 (2026-05-08): "Excellent architecture discussion, strong mobile optimization knowledge. Weak on modern iOS concurrency (async/await). Score: 8/10"
- Interviewer: "She's polished, asks good questions about team structure"
4. Offer history: None yet
AI Recommendation: "Score 8/10 is strong. Weakness on async/await is learnable and not role-critical (can ramp). Recommend Round 2 system design with her manager. Note strength on mobile optimization—could lead architecture on iOS perf initiative."
---
Week 3 - After Round 2 Manager Round + Ready to Offer:
AI Memory Lookup:
1. Candidate facts: (same, no changes)
2. Role requirements: (same)
3. Interview feedback:
- Round 1: 8/10 (architecture, mobile opt)
- Round 2 (2026-05-12): "Alignment on team vision, mentoring style, growth plan. Asked about IC vs. lead track. Score: 8/10"
- Manager notes: "She'd be great team lead. Clear communication. Asked about diversity hiring on team."
4. Offer history: None yet
AI Recommendation: "Two 8/10 scores, manager alignment. Within 1 week of screen-to-offer. Recommend offer:
- Base: $180k (target of her range, mid-range of role)
- Equity: 0.15%
- Signing bonus: $15k (to offset any RSUs vesting cliff)
- Target offer: $195.5k all-in
Expected acceptance: High (feedback was positive, no red flags, comp on-target)"
---
If she rejects or asks for more later:
AI would brain Round 2 notes ('asked about diversity hiring') and Round 1 notes ('strong culture fit signals') to adjust offer strategy: "She's signaling mission-alignment over pure comp. Consider flexibility on: early mentor rotation, diversity hiring involvement, IC vs. lead discussion."Without memory: Recruiter asks "Tell us about your background" in round 1, forgets details, Round 2 manager asks again. Alice feels evaluated repeatedly. No notes from Round 1 to inform offer strategy. Offer at $165k gets rejected, Alice says "That's way below my ask." No record of her salary expectation. Recruiter has to re-screen similar candidates days later because they don't recall Alice's fit.
With memory: Alice's background is understood once, not re-asked. Round 1 score (8/10) and specific feedback (strong architecture, weak on async) inform Round 2 questions. Offer is calibrated to her stated range (190k) and round scores. If offer gets rejected, recruiter understands why (comp structure issue vs. cultural fit) and can adjust. Similar candidates are matched against Alice's profile to avoid duplicates.
Memory Schema for HR & Recruitment
Design your memory schema for streamlined hiring workflows:
interface RecruitmentMemory {
agentId: string; // "candidate-{candidateId}" or "role-{roleId}"
namespace: "hr-recruitment";
// What was stored
content: string; // Resume, feedback, role spec, or offer
// How to retrieve it
type: "candidate_fact" | "interview_feedback" | "role_requirement" | "offer_history";
metadata: {
candidateId?: string;
roleId?: string;
// For candidate_fact
name?: string;
email?: string;
phone?: string;
location?: string;
skills?: string[]; // ["iOS", "Swift", "REST APIs"]
yearsOfExperience?: number;
salaryExpectation?: { min: number; max: number }; // In thousands
visaStatus?: string; // "US citizen", "H1B", "need sponsorship"
sourceChannel?: string; // "LinkedIn", "referral", "job board"
// For interview_feedback
roundNumber?: number;
interviewerName?: string;
feedbackDate?: string; // ISO 8601
score?: number; // 1-10
strengths?: string[];
weaknesses?: string[];
recommendation?: "move_forward" | "pass" | "hold";
// For role_requirement
requirementType?: string; // "must_have", "nice_to_have"
skill?: string;
yearsRequired?: number;
salaryRange?: { min: number; max: number };
// For offer_history
offerNumber?: number;
salary?: number; // In thousands
equity?: number; // Percentage
signingBonus?: number; // In thousands
offeredDate?: string; // ISO 8601
status?: "pending" | "accepted" | "rejected" | "expired";
rejectionReason?: string;
timestamp: string; // ISO 8601
};
}Use-Case Decision Table
When should you use structured vs. unstructured memory for recruitment?
| Decision | Structured (Typed Fields) | Unstructured (Free Text) | Example |
|---|---|---|---|
| Candidate profile | Yes, include skills, experience, location, visa, salary | Optionally include career narrative | { skills: ["iOS", "Swift"], yearsOfExperience: 8, salaryExpectation: { min: 170, max: 190 } } |
| Interview feedback | Yes, include round, score, strengths/weaknesses | Optionally include detailed interviewer notes | { roundNumber: 1, score: 8, strengths: ["architecture", "mobile-opt"], recommendation: "move_forward" } |
| Role specs | Yes, include must-have/nice-to-have, skills, salary range | Optionally include full job description text | { requirementType: "must_have", skill: "iOS", yearsRequired: 5, salaryRange: { min: 160, max: 200 } } |
| Offers | Yes, include salary, equity, signing bonus, status | No, structure enables offer tracking and negotiation | { offerNumber: 1, salary: 180, signingBonus: 15, status: "pending" } |
Rule of thumb: Typed fields for anything that filters or ranks candidates (skills, experience, salary range) or tracks pipeline progress (round number, offer status). Unstructured for interview narrative and role description.
Metrics: Impact of Agent Memory
Recruiting teams using agent memory see:
- 30% faster time-to-hire: Agent recalls candidate fit instantly, avoids re-screening and repeated interviews
- 25% reduction in candidate drop-off: Agent re-surfaces good candidates for new roles (no forgetting)
- 40% improvement in interview consistency: Same scoring rubric applied across all interviews, no conflicting assessments
- 20% reduction in failed hires: Manager feedback from round 2 informs offer and onboarding strategy
- 35% better offer acceptance rate: Compensation calibrated to candidate expectations and market signal
Implementation Checklist
- Design memory schema with skills, years of experience, salary range, visa status, and round scores
- Implement retrieval pipeline (candidate facts → role requirements → interview feedback → offer history)
- Log candidate ingestion: store resume parse, skills, location, salary expectation
- Log interview rounds: store feedback, score, strengths, weaknesses, recommendation
- Log offers: store salary, equity, bonus, offer date, status, rejection reason if declined
- Test with historical candidates: can agent avoid re-screening? Does it resurface fit candidates?
- Monitor metrics: time-to-hire, pipeline completion rate, offer acceptance rate
Next Steps
- Learn more: Check Memory Architectures for pipeline-scoped vs. candidate-lifetime memory in recruitment
- Reference: See Choosing Memory Schema for designing interview feedback storage
- Build: Start with Brain open-source for recruitment pilot, or try Managed Cloud for enterprise ATS integration