Skip to content

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 via USE_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: TypedDict for 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.Protocol structural typing for ChromaVectorStore and QdrantVectorStore.
  • Consequence: Clean dependency injection into IngestionService and JobMatcher with 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 BM25Okapi sparse 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_node decorator 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 AgentState leaks 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_expansions generated 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 ThreadPoolExecutor worker pool paired with Semaphore(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/elif chains in model factories violate the Open/Closed Principle.
  • Decision: Extensible PROVIDER_REGISTRY: dict[str, Callable] with register_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 via CompositeVectorStore with 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 NumPy InMemoryVectorStore fallback.
  • 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 in ParentDocumentStore + 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).