ADR: One Runtime, One Guardrail Owner, One Retrieval Contract
Status
Accepted
Context
The system had overlapping guardrails across orchestration and LangChain runtime, mixed queue durability guarantees, and inconsistent tool contracts. These overlaps increased duplicate tool calls, trace drift, and regression risk.
Decision 1: One guardrail owner
- Owner is orchestration in
backend/src/services/aso.service.ts. - Runtime-level fallback forcing in
backend/src/services/langchain/langchainToolTurn.service.tsis disabled. - Guardrail diagnostics stay centralized with:
guardrail_ownerguardrail_sourceguardrail_reason
Decision 2: One durable background queue path
- Durable queue target is BullMQ + Redis via
backend/src/services/backgroundJob.service.ts. - Memory embedding/chunk jobs use durable typed payloads.
- Legacy closure-based queue API remains as compatibility fallback only.
Decision 3: One retrieval contract
- Retriever supports keyword-only rows without embedding dependency in keyword branches.
- Scoring keeps keyword boosts bounded relative to vector quality.
- Prompt/runtime enforce hard token budgeting before model invocation.
Consequences
- Reduced duplicate fallback behavior and cleaner observability.
- Better restart safety for background jobs.
- More predictable tool and retrieval behavior under load.
Rollback switches
BG_QUEUE_DRIVER=legacyto fallback to in-memory queue behavior.PROMPT_HARD_TOKEN_BUDGET/PROMPT_RESERVED_OUTPUT_TOKENSto tune prompt truncation.