"""LangGraph agent framework setup for HR-ATS workflows. Pure module: no FastAPI imports and no HTTPException. This file only owns graph construction and lifecycle: init_agent() -> get_graph() -> build_graph() -> graph.compile() LLM client/config lives in llm_setup. Nodes live in agent.views. Run entrypoint lives in agent.execute_agent. """ from __future__ import annotations import logging from langgraph.graph import END, START, StateGraph from agent.models import AgentState from agent.views import finalize, match_jobs, prepare_context, route_after_prepare logger = logging.getLogger("agent") _graph = None def build_graph(): """Construct and compile the HR-ATS candidate matching graph.""" graph = StateGraph(AgentState) graph.add_node("prepare", prepare_context) graph.add_node("match_jobs", match_jobs) graph.add_node("finalize", finalize) graph.add_edge(START, "prepare") graph.add_conditional_edges("prepare", route_after_prepare) graph.add_edge("match_jobs", "finalize") graph.add_edge("finalize", END) return graph.compile() def get_graph(): """Return the cached compiled graph, building it on first use.""" global _graph if _graph is None: _graph = build_graph() logger.info("langgraph compiled") return _graph async def init_agent(): """Warm the compiled graph. LLM init stays on llm_setup.init_llm().""" get_graph() async def close_agent(): """Drop the cached graph.""" global _graph _graph = None logger.info("agent graph closed")