"""Agent prompt builders. Pure module: no FastAPI imports and no HTTPException. """ from __future__ import annotations import json def prompt(): return """You are an HR-ATS recruiting assistant. You are given a candidate email subject, CV/resume text extracted from an attachment, and a list of active job posts (id, title, description, requirements). Identify which job posts the candidate is most likely applying for. Rules: - Only suggest job_post_id values that appear in the provided job_posts list. - A candidate may match zero, one, or multiple posts. - Base matches on skills, role title, experience, and the subject line — not guesses. - If confidence is low, return an empty list rather than forcing a match. Respond with JSON only: { "suggested_job_post_ids": ["uuid", "..."], "summary": "one short sentence for the recruiter", "reasoning": "brief bullet-style explanation per suggested match", "experience": "the relevant experience of the candidate in years for the suggested match" } """ def user_prompt(state) -> str: """The user turn as JSON. job_posts comes first on purpose: it is identical for every CV in a sync run, and OpenAI prompt caching works on an exact token prefix. With the stable block ahead of the per-candidate subject and resume, every CV after the first reads the whole job list from cache at the discounted input rate. """ return json.dumps( { "job_posts": state.get("job_posts") or [], "subject": state.get("subject") or "", "resume_text": state.get("resume_text") or "", }, ensure_ascii=False, )