agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
88 lines (87 loc) • 4.11 kB
TypeScript
import { type FilterByDecayConfig } from '../stages/filterByDecay.js';
import { type SummarizeConfig } from '../stages/summarize.js';
import type { MemoryStore } from '../store/index.js';
import type { MemoryPipeline } from './types.js';
export interface DefaultPipelineConfig {
/** The store both subflows share. */
readonly store: MemoryStore;
/** How many recent entries to load per turn. Default 20 (see loadRecent). */
readonly loadCount?: number;
/**
* Token reserve for prompt headers / new user message / safety margin.
* Default 256.
*/
readonly reserveTokens?: number;
/** Minimum memory-token budget before the picker skips injection. Default 100. */
readonly minimumTokens?: number;
/**
* Hard cap on entries selected per turn, independent of tokens. Helps
* with "lost-in-the-middle" degradation. Default: no cap.
*/
readonly maxEntries?: number;
/**
* Optional tier constraint — e.g. `['hot']` to read only entries
* marked `hot` by the write side. Combines with `loadCount` (cap
* AFTER filter).
*/
readonly tiers?: ReadonlyArray<'hot' | 'warm' | 'cold'>;
/**
* Optional tier written entries are tagged with. Matches the `tiers`
* read filter when both sides want to coordinate tier policy.
*/
readonly writeTier?: 'hot' | 'warm' | 'cold';
/**
* Optional write-side TTL in milliseconds from `now`. Every written
* entry expires this long after storage. Useful for compliance
* retention windows.
*/
readonly writeTtlMs?: number;
/**
* Let old entries fade (9.5.0). When present, a `FilterByDecay` stage is
* composed between the load and the picker: every loaded entry is scored
* by AGE against `halfLifeMs` and dropped below `minScore`, so a
* long-running conversation stops rehearsing last month.
*
* Absent — the historical behaviour — means no decay stage is compiled at
* all, not a decay stage that keeps everything. What is not in the chart
* cannot cost anything or appear in the narrative.
*
* `defineMemory({ strategy: { kind: MEMORY_STRATEGIES.DECAY, halfLifeMs } })`
* is the door most consumers use; this is the same thing, spelled at the
* pipeline level so it composes with `loadCount` / the budget knobs.
*/
readonly decay?: FilterByDecayConfig;
/**
* Compress what falls out of the verbatim tail (9.14.0). When present, a
* `Summarize` stage is composed directly after the load: the oldest loaded
* entries become ONE summary entry written back to this same store, and
* recall becomes `[summary, ...recent verbatim]`.
*
* The stage's `store` and `ttlMs` are filled from THIS config — the summary
* lands in the same namespace as the turns it stands for, and under the same
* retention window, because a summary that outlived the messages it
* compressed is the leak `writeTtlMs` exists to prevent.
*
* Absent — the historical behaviour — means no summarize stage is compiled
* at all, not a summarize stage that never fires. What is not in the chart
* cannot cost anything or appear in the narrative.
*
* `defineMemory({ strategy: { kind: MEMORY_STRATEGIES.SUMMARIZE, recent,
* llm, model } })` is the door most consumers use; this is the same thing,
* spelled at the pipeline level so it composes with `loadCount` and the
* budget knobs.
*/
readonly summarize?: Omit<SummarizeConfig, 'store' | 'ttlMs'>;
/**
* Override for the formatter's header text. Omit to use the default
* "Relevant context from prior conversations..." phrasing.
*/
readonly formatHeader?: string;
/** Override for the formatter's footer text. Default: empty. */
readonly formatFooter?: string;
}
/**
* Build the default read + write pipelines sharing a single store.
* Returns two FlowChart subflows ready to be mounted by the wire layer.
*/
export declare function defaultPipeline(config: DefaultPipelineConfig): MemoryPipeline;