agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
61 lines (60 loc) • 3.63 kB
TypeScript
/**
* toolDispatch — the run's own tool dispatch, delivered as `ctx.tools`.
*
* Pattern: a deps-closure factory beside `toolArtifacts` / `toolProgress` in
* the tool-calls handler; this module holds the PURE half (the
* dispatch object over a lookup + an inner-context maker) so the
* handler wires closures and nothing else.
* Role: core/agent — composition over the registry (the runbookAsTool
* substrate; any tool may consume it).
* Emits: nothing itself. Inner executes flow through the tool's own
* channels (`ctx.progress`, its result); they do NOT fire
* `tool_start`/`tool_end` — an inner call is the OUTER call's work,
* not a turn of the model's, and synthesizing model-facing events
* for it would put calls in the record the model never made.
*
* What an inner call is NOT (phase 1, refused loudly, never silently):
* - it cannot pause — a `checkIn` tool or a credential that needs
* interactive consent refuses by name (a pause the inner tool itself
* RAISES, `requestInput` or `pauseHere`, is not refused: it passes up as
* the OUTER call's pause, and an `absence` it declares is filed under the
* outer call — `semantics/coverage/README.md` § 4);
* - it cannot redeem artifact refs — a `wants` tool refuses by name
* (dispatch-time resolution belongs to the model-facing loop);
* - it does not see ToolProvider-delivered tools — there is no build-time
* list of those (the 9.72.0 caveat, carried forward honestly);
* - it does not carry `ctx.tools` itself — composition depth stops at one,
* the same bound the runbook grammar declares for sub-runbooks;
* - it does not apply argument rules — a tool that declares `askOrAssume`
* refuses an inner call that leaves a ruled argument out (the inputs
* layer fills and records only the model's own calls). A declared
* `period`'s forms are ALTERNATIVES: the window is owed once, and a call
* that gives one form whole (a look-back, or both bounds) is not refused
* for the other forms' arguments.
*/
import type { Tool, ToolDispatch, ToolExecutionContext } from '../../tools/tools.js';
/** What the handler wires in — everything the dispatch cannot know itself. */
export interface AgentToolDispatchDeps {
/** Name → Tool over the agent's dispatch map (static + skill-carried).
* Provider-delivered tools are invisible by construction. */
readonly lookup: (name: string) => Tool | undefined;
/**
* Compose the execution context for ONE inner call: the outer call's own
* facts with `hasArtifacts: false`, a derived `toolCallId` (`seq` makes it
* unique within the outer call), and NO `tools` of its own.
*/
readonly innerContext: (toolName: string, seq: number) => ToolExecutionContext;
}
/**
* Build the `ctx.tools` dispatch for one outer tool call.
*
* `call` resolves the inner tool's declared `needs` through the inner
* context's own credential provider (fail-closed — the provider throws its
* teaching refusal when none is attached), refuses the shapes an inner call
* cannot honor (see the module header), validates the declared input schema
* before creating an inner context, executes, and returns the result exactly
* as the tool returned it. Policy about what a result MEANS — an
* absence that should short-circuit, a coverage ledger that should fold —
* belongs to the consumer wrapping this dispatch, never here.
*/
export declare function agentToolDispatch(deps: AgentToolDispatchDeps): ToolDispatch;