summary.ts reduces those candidates into the compact prompt block used by the agent turn.
Retrieval pipeline
pre_turn requires a query. If the caller omits limits, the lower-level loop defaults to limit: 5, maxItems: 8, and maxItemChars: 500. The native agent turn passes tighter values: limit: 12, maxItems: 6, maxItemChars: 120, and budget.maxCharacters: 900.
Embeddings
embedding.ts uses MongoDB’s AI gateway to reach Voyage embeddings.
Query and document embeddings use separate ValKey keys. The same text can produce different vectors because Voyage’s asymmetric retrieval models treat query and document inputs differently.
The embedder has no silent provider fallback. If embeddings are unavailable, the operation fails instead of mixing vector spaces.
Vector search
hybridVectorSearch() builds a durable Mongo filter, runs Atlas $vectorSearch, applies a score threshold, and bumps access counters for returned rows.
If Atlas vector search fails, or if the vector query returns no usable results, the runtime falls back to keyword search over recent scoped documents. That fallback keeps recall available during vector-index outages, but it is not treated as equivalent to semantic retrieval.
Optional Atlas prefilter fields come from MEMORY_VECTOR_PREFILTER_FIELDS. The runtime still applies memory filters after search, so prefilter configuration is an optimization, not the trust boundary.
Ranking
applyVectorRanking() applies ranking in this order:
Rerank is fail-soft. Missing Cloudflare credentials, timeouts, or upstream failures log a warning and keep the decayed order.
Prompt packing
Layer search returns records. The prompt packer turns them into text.
Layer priorities are:
The packer dedupes candidates by a normalized fingerprint. It has a specific user-turn fingerprint for transcript-like rows so repeated session summaries do not crowd out durable facts.
Output shape
The final prompt always starts with the same header:pre_turn also returns structured accounting: