UNPKG

agentfootprint

Version:

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

62 lines • 3.26 kB
"use strict"; /** * defineRelevanceHint — an advisory system-prompt note for an ambiguous entry. * * When `entryByRelevance()` picks the starting skill but the top candidates are a * NEAR-TIE under the relevance scorer, this injection drops a NON-BINDING note into * the system prompt for that turn: "an offline scorer found these close; it can't * see the conversation — use your own judgment." A hint, not an order. * * Anti-anchoring is the point (the proxy is a rough keyword match, not the model's * own reasoning), so the note is framed as advisory and only fires on a real tie. * It rides the normal injection path (`context.evaluated`) — no new event. Reads * `ctx.entryScores` (set by the PickEntry stage), so it needs `.entryByRelevance()`. * * Add it explicitly: `Agent.create(...).skillGraph(graph).injection(defineRelevanceHint())`. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.defineRelevanceHint = exports.READS_ENTRY_SCORES_METADATA_KEY = void 0; /** * The metadata marker that says "this injection reads `ctx.entryScores`" (8.7.0). * * Only `.entryBy()` / `.entryByRelevance()` ever write `entryScores` — the PickEntry * stage runs a scorer and stamps them. Mounted on a graph with no scorer, the hint's * trigger simply can never be true, and nothing said so: the injection registered, * evaluated false on every iteration for the life of the agent, and the author saw a * feature that was configured and inert. * * A marker rather than an id match, because the id is the caller's to choose * (`defineRelevanceHint({ id })`) — matching on `'relevance-hint'` would miss every * renamed one and would false-positive on anybody else's injection of that name. * `AgentBuilder.build()` reads it and dev-warns. */ exports.READS_ENTRY_SCORES_METADATA_KEY = 'readsEntryScores'; /** Is the top entry a near-tie with the runner-up? */ function isNearTie(scores, threshold) { if (!scores || scores.length < 2) return false; const sorted = [...scores].sort((a, b) => b.relevance - a.relevance); return sorted[0].relevance - sorted[1].relevance < threshold; } function defineRelevanceHint(options = {}) { const threshold = options.threshold ?? 0.15; return { id: options.id ?? 'relevance-hint', flavor: 'instructions', description: 'Advisory note when the entry skill was a near-tie under the relevance scorer', trigger: { kind: 'rule', activeWhen: (ctx) => ctx.iteration === 1 && isNearTie(ctx.entryScores, threshold), }, metadata: { [exports.READS_ENTRY_SCORES_METADATA_KEY]: true }, inject: { systemPrompt: 'Note: an offline relevance scorer found two or more starting skills nearly tied for ' + 'this request. That scorer only matches description keywords and cannot see the ' + 'conversation, so treat the auto-selected skill as a weak hint — not an instruction. ' + 'Use your own judgment about which skill actually fits; if a different one is clearly ' + 'better, switch to it.', }, }; } exports.defineRelevanceHint = defineRelevanceHint; //# sourceMappingURL=defineRelevanceHint.js.map