agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
64 lines (63 loc) • 2.82 kB
TypeScript
import type { FlowChartBuilder } from 'footprintjs';
import type { MemoryState } from './types.js';
import { type TokenCounter } from './tokenize.js';
/**
* Reusable shape for a **composable pipeline segment** — a function that
* appends one or more stages to a builder and returns the builder. This
* is the memory layer's convention for packaging multi-stage work
* (decider + branches, multi-stage sub-pipelines) as a single unit that
* consumers can drop into any flowchart:
*
* ```ts
* let b = flowChart<MyState>('Seed', seed, 'seed');
* b = pickByBudget(config)(b); // appends a decider + 3 branches
* b = b.addFunction('Format', fmt, ...);
* ```
*
* Generic in `T` so segments targeting the memory layer can be composed
* into host flowcharts whose state extends `MemoryState`. Future
* segments (NarrativeMemory, SemanticRetrieval, FactExtraction) follow
* the same shape for uniform composition ergonomics.
*/
export type PipelineSegment<T extends object> = (builder: FlowChartBuilder<T>) => FlowChartBuilder<T>;
export interface PickByBudgetConfig {
/**
* Tokens to keep in reserve — not used for memory. Default 256.
* Covers system-prompt overhead, new user message headroom, and safety
* margin against token-counter approximation error. Tune per model.
*/
readonly reserveTokens?: number;
/**
* Hard floor on memory tokens. If the budget minus reserve is less than
* this, NO memory is injected (better to skip than inject a fragment).
* Default 100 — under 100 tokens of memory is usually worse than none.
*/
readonly minimumTokens?: number;
/**
* Pluggable token counter — defaults to `approximateTokenCounter`
* (1 token ≈ 4 chars). Swap for a real tokenizer when accuracy matters.
*/
readonly countTokens?: TokenCounter;
/**
* Optional cap on the NUMBER of entries, independent of tokens.
* Useful when the budget is large enough to include hundreds of
* entries but the LLM's "lost-in-the-middle" effect degrades quality
* past ~20. Default: no cap (budget is the only limit).
*/
readonly maxEntries?: number;
}
/**
* Append the pick-by-budget decider + branches to `builder`. Returns
* the builder so calls chain naturally:
*
* ```ts
* let b = flowChart<MemoryState>('LoadRecent', loadRecent(config), 'load-recent');
* b = pickByBudget(pickConfig)(b);
* b = b.addFunction('Format', formatDefault(formatConfig), 'format-default');
* ```
*
* Generic in `T` so consumers whose scope extends `MemoryState` (e.g.,
* an AgentLoopState that embeds memory fields) can compose this into
* their own pipeline without casting.
*/
export declare function pickByBudget<T extends MemoryState = MemoryState>(config?: PickByBudgetConfig): PipelineSegment<T>;