agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
123 lines (122 loc) • 6.54 kB
TypeScript
/**
* conversationRedaction — the names an agent's record carries the
* conversation under, as one footprintjs `RedactionPolicy`.
*
* Pattern: a vocabulary the library owns, handed out as data (a policy), with
* the caller's own selectors joined on (`unionRedactionPolicies`).
* Role: the Map half of `src/redaction/` for the question "what do I name
* to keep the conversation out?" — `Agent.create({ redact })` is the
* one door; this is the value most callers hand it.
*
* WHY THE LIBRARY OWNS THE LIST. footprintjs selects by NAME: a policy keeps a
* value out of every record when it names the state key, or the event field
* (at any depth), the value travels under. An agent's record carries the
* conversation under many names, nearly all of them the library's own — the
* person's message, the model's words and thinking, tool arguments and
* results, what memory and retrieval recalled, what was injected into the
* model's context, a paused call's arguments, the draft a schema check
* rejected. A caller cannot be expected to know them; the library can, and
* `test/redaction/agent-redaction.vocabulary.test.ts` runs each feature listed
* in `CONVERSATION_FEATURES` with a canary in every place the conversation
* goes, and fails when a canary reaches any record.
*
* WHAT IS NOT ON IT, by design:
* - values an app's own tools or rules put in the record under names of
* their own (a tool's result is covered by `result`, but a field inside an
* event your middleware emits is yours to name) — join them:
* `conversationRedaction({ patterns: [/ssn|email/i] })`;
* - error text written by code (`error`, `errorMessage`, `lastError`): a
* message a tool or provider throws can quote what it failed on, and
* `error` also names a flag the record's readers count on
* (`stream.tool_end`'s `error: true`). On an EVENT it is kept out anyway,
* under ANY policy: the value-kind rule serves every string that is not a
* library word as the placeholder (`knownStrings.ts`) — a parser message
* that quotes the model's draft included. In STATE the name is yours to
* add;
* - structure: counts, kinds, flags, timings and verdict words stay
* readable — the record still shows WHAT happened, without the words;
* - content the library quotes under names of its own (a validation issue's
* quoted argument, a check-in's evidence pack, a matcher's witness, a
* route guard's judged result, the words of a tool's coverage declaration
* and a described result's data on their events, …) is not named here:
* generic names (`value`, `text`, `note`, `checked`) would hide structure
* across every event. On events it is kept out under ANY policy by the
* value-kind rule (`knownStrings.ts`): no string survives that is not a
* library word.
*
* Names it shares with structure, kept out with it: `permission.check`'s
* `result` (its verdict word — a refused call still reads as refused, from
* `stream.tool_end`'s `notExecuted`).
*/
import type { RedactionPolicy } from 'footprintjs';
import { type CarriedRedactionPolicy } from './policy.js';
/** The features whose records the vocabulary is proven against, by the test above. */
export declare const CONVERSATION_FEATURES: readonly string[];
/**
* The vocabulary's VERSION — derived from its own contents (every key, pattern
* and field selector, sorted), so it changes whenever the list does and never
* waits on a hand bump. A carried policy that keeps the conversation out
* records the version it was built under (`carriedRunPolicy`); a resumed leg
* whose record names another version is covered by the CURRENT vocabulary as
* well (`withCurrentVocabulary`) — fail closed, never the older list alone.
*/
export declare const VOCABULARY_VERSION: string;
/**
* `policy` as a run's state carries it (`AgentState.runRedaction`) — with the
* vocabulary version it was built under when it keeps the conversation out.
*
* @internal
*/
export declare function carriedRunPolicy(policy: RedactionPolicy): CarriedRedactionPolicy;
/**
* A carried policy as a resumed leg is covered by it: joined with the CURRENT
* vocabulary when its record names another version (`version`, read off the
* checkpoint). An older list lacks the names an upgrade added — names that
* keep the conversation out of the leg's STATE, its snapshot and its commit
* log. Joining the current list keeps the leg at least as covered as the run
* that paused. Same version, or none: the policy as carried.
*
* @internal
*/
export declare function withCurrentVocabulary(policy: RedactionPolicy | undefined, version: string | undefined): RedactionPolicy | undefined;
/**
* The policy that keeps an agent's conversation out of every record it
* retains or serves — joined with `extra`, the names your own app adds.
*
* Hand it to the one door, `Agent.create({ redact })`. What it covers, what it
* leaves readable and what it does not name are in this file's header and in
* `src/redaction/README.md`.
*
* @param extra your own selectors (`keys`, `patterns`, `fields`,
* `emitPatterns`, `diagnostics`), validated like `redact`
* itself; joined, never replacing the library's names.
* @returns a frozen `RedactionPolicy`.
*
* @example
* ```ts
* import { Agent } from 'agentfootprint';
* import { conversationRedaction } from 'agentfootprint/security';
*
* const agent = Agent.create({
* provider,
* model: 'claude-sonnet-4-5',
* redact: conversationRedaction({ patterns: [/ssn|email|phone/i] }),
* }).build();
* ```
*/
export declare function conversationRedaction(extra?: RedactionPolicy): RedactionPolicy;
/**
* Whether `policy` keeps an agent's WHOLE conversation out of its records —
* every name the vocabulary lists selected by its rule (a pattern of the
* policy's own that covers a name counts), `conversationRedaction()` or more.
*
* The question a chart-backed tool asks before it hands the MODEL a value the
* calling run's policy selects (`core/servableSnapshot.ts` ·
* `modelFacingState`): the value travels on in the calling run's conversation
* — the tool's result in its history and events, whatever the model then
* says — so only a calling run whose records keep the conversation out keeps
* that value out of them too.
*
* @internal
*/
export declare function keepsConversationOut(policy: RedactionPolicy | undefined): boolean;