UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

60 lines (59 loc) • 3.01 kB
/** * messageFrom — which runners read `AgentInput.messageFrom`, and the one input * a composition hands them. * * Pattern: a registry of readers (a `WeakSet`), and one helper every * composition calls where it hands one runner another runner's output * as its message. * Role: core/ leaf. No imports, no state beyond the set. A composition * (`core-flow/Sequence.ts`, `core-flow/Loop.ts`, * `core-flow/Workflow.ts`, `core-flow/Graph.ts`) passes * `messageFrom: 'composed'` ONLY to a runner that reads it — an * `Agent` whose declared sources are armed * (`.findings({ argumentSources: true })` or * `.inputsLayer({ argumentSources: true })`), or one armed with a * time reader (`.time({ reader })`, which reads only a person's * words — `core/agent/stages/seed.ts`) — so every other * composition hands its steps the input it always did, byte for byte. * Emits: N/A. * * ## Why a composition marks the message * * The inputs layer's declared sources check a quote the model says came from * the PERSON against the person's own messages (`core/agent/arguments/checks.ts` * · `checkSource`). In a composition, a later step's message is an earlier * step's output — another model's words. A quote found only there must never * count as "the person said it" (`failed: 'composed-message'`), and only the * composition knows where its step's message came from. */ /** * Register a runner that reads `AgentInput.messageFrom` — `Agent` calls this * for itself when its declared sources are armed or a time reader is armed. * Nothing else needs to. */ export declare function readsMessageFrom(runner: object): void; /** * A composition that holds a reader reads the marker too: nested in another * composition, it may be handed a composed message itself, and it passes that * on to the child it hands its own message to — the handed-in input is a key * of its own scope (`parent.messageFrom` in its children's input mappings). * Called by each composition's constructor with its children. */ export declare function readsMessageFromIfAny(composition: object, children: readonly object[]): void; /** * The input a composition hands `runner` when its message is ANOTHER runner's * output: `input` with `messageFrom: 'composed'` for a runner that reads the * marker, and `input` itself — the same reference — for every other runner. * A structured hand-off (`workflow()`, `graph()`) is marked whole: every key * of it is another runner's output, its `message` included — and for a * runner that reads the marker, a `messageFrom` the earlier runner returned * is overwritten, never trusted. * * @example * ```ts * inputMapper: (parent) => composedInput(step.runner, { message: parent.current as string }), * ``` */ export declare function composedInput<I extends object>(runner: object, input: I): I | (I & { readonly messageFrom: 'composed'; });