Trayntrayn.ai

Retrieval

How Trayn retrieves relevant memories for the agent's current state.

RetrieverAdapter Interface

import type { EnvironmentState, RetrievalConfig } from "@trayn/memory";
import type { RetrievalOutput } from "@trayn/memory";

interface RetrieverAdapter {
  retrieve(
    sessionId: string,
    currentRunId: string,
    input: {
      currentEnv: EnvironmentState;
      currentStateEmbedding: number[];
    },
    config?: Partial<RetrievalConfig>,
  ): Promise<RetrievalOutput>;
}

RetrievalConfig Schema

import { retrievalConfigSchema } from "@trayn/memory";

// retrievalConfigSchema validates:
interface RetrievalConfig {
  envThreshold: number;  // 0.0–1.0, minimum IoU score to consider (default: 0.7)
  topK: number;          // Max candidates after env filtering (default: 10)
  finalK: number;        // Final number of memories returned (default: 2)
}

Default Pipeline (DefaultRetriever)

The built-in DefaultRetriever uses a multi-stage pipeline:

  1. Load — Fetch all graded memories for the session (excluding current run)
  2. Environment IoU — Score each memory's envPre.elements against current page elements using Intersection over Union. Filter below envThreshold
  3. Top-K — Keep the top topK by environment score
  4. Cosine Ranking — Score by cosine similarity between the memory's internalStateEmbedding and the current state embedding. Rank by combined score (65% env + 35% intent)
  5. Dedup — Collapse memories with identical action signatures (same action type + target + value)
  6. Final Selection — Pick finalK memories, prioritizing at least one AVOID and one REPEAT

Custom Retriever Example

import type { RetrieverAdapter } from "@trayn/memory";
import { setRetriever } from "@trayn/memory";

class VectorDBRetriever implements RetrieverAdapter {
  async retrieve(sessionId, currentRunId, input, config) {
    const results = await myVectorDB.query({
      embedding: input.currentStateEmbedding,
      filter: { sessionId },
      topK: config?.finalK ?? 2,
    });

    return {
      memories: results.map((r) => ({
        memory: r.metadata,
        envScore: r.score,
        intScore: r.score,
      })),
      debug: {
        totalLoaded: results.length,
        envMatched: results.length,
        envTopK: results.length,
        stateRanked: results.length,
        deduped: results.length,
        aboveThreshold: results.length,
        selected: results.length,
      },
    };
  }
}

setRetriever(new VectorDBRetriever());

Dependency Injection

import { setRetriever, getRetriever } from "@trayn/memory";

// Set a custom retriever
setRetriever(myRetriever);

// Use the retriever (falls back to DefaultRetriever if none set)
const result = await getRetriever().retrieve(sessionId, runId, input);

Unlike getGrader(), getRetriever() automatically falls back to DefaultRetriever if no custom retriever is configured. You only need setRetriever() when replacing the default pipeline.

On this page