Architecture Decision Records (ADRs)¶
This directory contains the individual Architecture Decision Records (ADRs) for Yojaka AI (Agentic Profile Matching Engine).
🌐 Interactive Documentation: Browse all ADRs with instant search on the Yojaka AI Documentation Site.
📑 ADR Catalog & Executive Matrix¶
| ADR | Title | Status | Release | Category |
|---|---|---|---|---|
| ADR-001 | Model Context Protocol (MCP) Dual-Mode Gateway Architecture | Accepted | v0.6.0 | Protocol & Tooling |
| ADR-002 | Using TypedDict for AgentState Over Pydantic BaseModel | Accepted | v0.7.0 | State & Serialization |
| ADR-003 | BaseVectorStore Structural Protocol Over abc.ABC | Accepted | v0.8.2 | Storage Abstraction |
| ADR-004 | BM25 Okapi Corpus Index Caching with Invalidation | Accepted | v0.8.3 | Performance & Retrieval |
| ADR-005 | Idempotent upsert() Ingestion with Section-Scoped Chunk Keys | Accepted | v0.8.2 | Data Integrity |
| ADR-006 | Celery + Redis Task Queue for Asynchronous Heavy Operations | Accepted | v0.8.6 | Distributed Workers |
| ADR-007 | Structured JSON Logging & Pluggable Tracing Pipeline | Accepted | v0.9.1 | Observability & APM |
| ADR-008 | Multi-Factor Hybrid Candidate Scoring & Grounded LLM Recommendation Hierarchy | Accepted | v1.0.0 | AI Evaluation & Guardrails |
| ADR-009 | LLM-Driven Intent Routing, Dynamic Anchors & Semantic Caching | Accepted | v1.2.0 | Semantic Routing |
| ADR-010 | Multi-Provider LLM Abstraction with Sarvam AI Indic Model Integration | Accepted | v1.1.0 | Multi-Provider & Indic Scale |
| ADR-011 | Stateless Credential Isolation & Checkpoint Security | Implemented | v1.2.0 | Security (CWE-312) |
| ADR-012 | Functional State Immutability & LangGraph Node Invariance | Implemented | v1.2.0 | State & Reliability |
| ADR-013 | Dynamic Generative LLM Skill Expansion & Semantic Equivalence Matching | Implemented | v1.2.0 | Domain Intelligence |
| ADR-014 | Concurrency-Controlled Asynchronous Candidate Screening | Implemented | v1.2.0 | Throughput & Latency |
| ADR-015 | Open/Closed LLM Provider Registry Pattern | Accepted | v1.3.0 | Architecture & OCP |
| ADR-016 | Zero-Disk In-Memory Resume Ingestion | Implemented | v1.2.0 | Ingestion & Privacy |
| ADR-017 | Layout-Aware Section Parsing, Anthropic Contextual Retrieval & Two-Stage Reranking | Implemented | v1.4.0 | Ingestion & Retrieval |
| ADR-018 | Calibrated Margin-Based Intent Routing, Native LangGraph Commands & Parallel Dual-Rubric Subgraphs | Implemented | v1.5.0 | Agent Architecture & Evaluation |
| ADR-019 | Advanced RAG Architecture: HyDE Query Synthesis, Parent-Doc Chunking & Air-Gapped Local Inference | Implemented | v1.6.0 | Advanced RAG & Privacy |
Executive Summaries¶
ADR-001: Model Context Protocol (MCP) Dual-Mode Gateway Architecture¶
- Context: Enabling both local in-process testing and standardized FastMCP JSON-RPC 2.0 tool execution.
- Decision: Dual-mode client manager (
fs_client.py,mcp_client.py) toggled dynamically viaUSE_MCP=True/False. - Consequence: Zero-overhead local testing + full microservice protocol compliance.
ADR-002: Using TypedDict for AgentState Over Pydantic BaseModel¶
- Context: Minimizing LangGraph state checkpointer serialization overhead while guaranteeing type safety.
- Decision:
TypedDictfor graph state transitions; strict Pydantic V2 models exclusively at LLM tool boundaries. - Consequence: Eliminates checkpointer overhead and avoids custom object serialization issues.
ADR-003: BaseVectorStore Structural Protocol Over abc.ABC¶
- Context: Enabling swappable vector store backends without framework class coupling.
- Decision:
typing.Protocolstructural typing forChromaVectorStoreandQdrantVectorStore. - Consequence: Clean dependency injection into
IngestionServiceandJobMatcherwith zero vendor lock-in.
ADR-004: BM25 Okapi Corpus Index Caching with Invalidation¶
- Context: Rebuilding the BM25 index on every search query adds \(O(N)\) latency (~200ms).
- Decision: Cache
BM25Okapisparse matrix with MD5 fingerprint checks across the indexed corpus. - Consequence: Reduces hybrid search query latency from ~200ms to ~0.1ms.
ADR-005: Idempotent upsert() Ingestion with Section-Scoped Chunk Keys¶
- Context: Duplicate vector entries skew term frequencies and corrupt similarity scores on re-ingestion.
- Decision: Deterministic chunk IDs formatted as
{filename}_chunk_{section_index}. - Consequence: 100% idempotent document ingestion with zero collection bloat.
ADR-006: Celery + Redis Task Queue for Asynchronous Heavy Operations¶
- Context: Multi-document PDF parsing and batch LLM screening block web UI event loops.
- Decision: Celery distributed workers with Redis broker and Docker Compose orchestration.
- Consequence: Offloads high-latency background operations from the web application UI thread.
ADR-007: Structured JSON Logging & Pluggable Tracing Pipeline¶
- Context: Unformatted console output lacks structured timestamps and APM latency metrics.
- Decision: Single-line JSON log formatter +
@trace_nodedecorator supporting Langfuse and OpenTelemetry. - Consequence: Production-grade APM log compatibility with millisecond execution tracking.
ADR-008: Multi-Factor Hybrid Candidate Scoring & Grounded LLM Recommendation Hierarchy¶
- Context: Preventing score compression, magic-number overrides, and LLM qualification hallucinations.
- Decision: Min-max normalized vector + BM25 scoring with grounded status hierarchy and safety guardrails.
- Consequence: Deterministic scoring and elimination of hallucinated qualifications.
ADR-009: LLM-Driven Intent Routing, Dynamic Anchors & Semantic Caching¶
- Context: Brittle keyword arrays fail on natural language phrasing, while static string examples struggle to disambiguate tech/web searches from candidate screening.
- Decision: Primary LLM structured intent classification (
RouteDecision) + dynamic LLM anchor synthesis (generate_dynamic_intent_anchors) + in-memory LRU query routing cache (_ROUTING_CACHE). - Consequence: Sub-millisecond 0ms repeat query execution, dynamic prototype adaptability, and complete separation between candidate screening and general tech/web inquiries.
ADR-010: Multi-Provider LLM Abstraction with Sarvam AI Indic Model Integration¶
- Context: Multilingual candidate screening (Indic languages) and zero vendor lock-in.
- Decision: Unified provider factory with Sarvam AI (
sarvam-105b), Groq, Gemini, and OpenAI. - Consequence: Native Indic language resume screening with seamless provider switching.
ADR-011: Stateless Credential Isolation & Checkpoint Security¶
- Context: Storing API keys in
AgentStateleaks credentials into checkpoint dumps and traces (CWE-312). - Decision: Purge credentials from state; inject pre-instantiated LLM via
RunnableConfig(configurable["llm"]). - Consequence: Eliminates credential leakage risk across state checkpoints, logs, and telemetry.
ADR-012: Functional State Immutability & LangGraph Node Invariance¶
- Context: In-place dictionary mutations break LangGraph checkpoint idempotency and retry safety.
- Decision: Pure functional node transitions with copy-on-write candidate dict updates (
{**c, ...}). - Consequence: Deterministic checkpointing and race-free node re-execution.
ADR-013: Dynamic Generative LLM Skill Expansion & Semantic Equivalence Matching¶
- Context: Hardcoded skill lists and static manual taxonomy YAMLs create endless maintenance overhead and fail on rapidly evolving technology stacks.
- Decision: LLM-driven structured
skill_expansionsgenerated dynamically during requirement extraction (Cloud\(\to\)AWS,GCP,Azure,Kubernetes), paired with regex-based open-ended resume section parsing. - Consequence: Zero-maintenance taxonomy, deep conceptual equivalence matching (AWS satisfies Cloud), and automatic adaptation to emerging frameworks.
ADR-014: Concurrency-Controlled Asynchronous Candidate Screening¶
- Context: Sequential LLM screening causes 60–75s UI freezes; unbounded parallel calls trigger 429 rate limits.
- Decision: Bounded
ThreadPoolExecutorworker pool paired withSemaphore(max_concurrent=2). - Consequence: 3.5x throughput improvement (~75s \(\to\) ~15–20s) with rate-limit protection.
ADR-015: Open/Closed LLM Provider Registry Pattern¶
- Context: Procedural
if/elifchains in model factories violate the Open/Closed Principle. - Decision: Extensible
PROVIDER_REGISTRY: dict[str, Callable]withregister_provider()API. - Consequence: Open/Closed compliance; zero-code modification when adding new model providers.
ADR-016: Zero-Disk In-Memory Resume Ingestion & Ephemeral PII Isolation¶
- Context: Staging uploaded resumes on server disks and sharing persistent collections violates enterprise privacy policies, risks multi-tenant data leaks, and fails on ephemeral container clouds.
- Decision: In-memory binary buffer processing (
io.BytesIO) using PyMuPDF and python-docx, layered viaCompositeVectorStorewith session-isolated ephemeral in-memory ChromaDB collections (chromadb.EphemeralClient()). - Consequence: 100% server disk isolation, complete multi-tenant session isolation for uploaded PII, anti-XSS HTML escaping, zero residual candidate files, and seamless support for ephemeral/serverless runtimes.
ADR-017: Layout-Aware Section Parsing, Anthropic Contextual Retrieval & Two-Stage Reranking¶
- Context: Fixed-character chunking destroys multi-role work histories; isolated chunk embeddings collapse critical candidate context; bi-encoder coarse retrieval lacks fine-grained joint attention.
- Decision: PyMuPDF bounding-box visual paragraph parsing + Anthropic 50–80 word metadata banner prepending + Stage 2 Cross-Encoder joint reranker (
ms-marco-MiniLM-L-6-v2) with Sigmoid calibration and Reciprocal Rank Fusion + pure NumPyInMemoryVectorStorefallback. - Consequence: Eliminates section truncation, preserves work history integrity, enhances top-rank precision, ensures 100% crash-free serverless cloud runtime compatibility, while keeping raw candidate text pristine for recruiter UI views.
ADR-018: Calibrated Margin-Based Intent Routing, Native LangGraph Commands & Parallel Dual-Rubric Subgraphs¶
- Context: Input intent classification oscillated between high-latency LLM calls and brittle string heuristics; conditional edge boilerplate cluttered graph state transitions; candidate audits suffered from slow multi-agent debate loops; monolithic state increased coupling.
- Decision: Mathematical confidence margin gate (\(\Delta = \text{Top1} - \text{Top2} \ge 0.12\)) routing confident queries in <2ms at $0 LLM cost while escalating ambiguity to structured LLMs + LangGraph 1.x native
Command(goto=..., update={...})with destination routing + concurrent dual-rubric evaluation (Technical Architecture 60% + Domain Fit 40%) with deterministic mathematical aggregation + isolated typed subgraphs (JDAnalyzerSubgraph,TalentRetrievalSubgraph,DeepScreeningSubgraph,SynthesisSubgraph). - Consequence: Zero misrouting errors, sub-millisecond confident query dispatch, committee-grade evaluation fidelity in a single round with ~1.2s wall-clock latency, and modular, clean state graph pipelines.
ADR-019: Advanced RAG Architecture: HyDE Query Synthesis, Parent-Document Chunking & Air-Gapped Local Inference¶
- Context: Terse recruiter queries suffer from semantic vocabulary mismatch against accomplishment-dense resumes; naive small chunking fragments career trajectories and causes deep screening hallucinations; cloud LLM egress raises privacy compliance concerns for sensitive resumes.
- Decision: Hypothetical Document Embeddings (
HyDEService) synthesizing candidate profiles before vector search + dual-granularity Small-to-Big chunk mapping (ParentDocumentService) linking 150–250 token child chunks in ChromaDB to 1,000–1,500 character parent sections inParentDocumentStore+ pre-retrieval faceted metadata filtering (FacetedFilter) + air-gapped local model inference (LocalInferenceService) supporting Ollama and vLLM daemons via OpenAI-compatible endpoints with automated health probing. - Consequence: Bridges query-resume semantic vocabulary gap (+9.1% Recall@10, +9.5% MRR), preserves complete section narratives during dual-rubric screening, enables 100% zero-cloud sovereign privacy deployments, and eliminates state-level API key storage (resolving Finding 6).