agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
150 lines • 6.75 kB
TypeScript
/**
* SkillRegistry — centralized governance for Skills across one or
* more Agents.
*
* Most apps register Skills directly on the Agent via `.skill(s)`.
* Once you have multiple Agents that share a common skill catalog
* (a customer-support pool, a research team, a multi-step workflow
* where each step uses different overlapping skills), hand-syncing
* `.skill()` calls per Agent gets fragile.
*
* `SkillRegistry` is the answer: register once, attach to many
* Agents via `.skills(registry)`. Add a Skill to the registry and
* every consumer Agent picks it up at next build.
*
* @example
* const registry = new SkillRegistry();
* registry.register(billingSkill);
* registry.register(refundSkill);
*
* const supportAgent = Agent.create({ provider }).skills(registry).build();
* const escalationAgent = Agent.create({ provider }).skills(registry).build();
*
* // Add a new skill — both agents pick it up at next build.
* registry.register(complianceSkill);
*/
import type { Injection } from './types.js';
import { type SkillToolPair } from './skillTools.js';
import { type SurfaceMode } from './factories/defineSkill.js';
/**
* Options for `new SkillRegistry({...})`. All fields are optional;
* the empty-object form (`new SkillRegistry()`) is the v2.4 surface.
*
* @see SkillRegistry.resolveForSkill — applies the cascade
*/
export interface SkillRegistryOptions {
/**
* Registry-level default `surfaceMode`. Applies to skills whose own
* `surfaceMode` is `'auto'` (the `defineSkill` default). Per-skill
* `surfaceMode` always wins; this is the fallback BEFORE the global
* `resolveSurfaceMode(provider, model)` rule.
*
* Use case: a registry shared across agents pointed at the same
* provider can lock surfaceMode here once instead of repeating it
* on every `defineSkill`.
*/
readonly surfaceMode?: SurfaceMode;
/**
* Provider name used as a hint when resolving `surfaceMode: 'auto'`
* inside this registry. Most consumers don't set this — runtime code
* passes the provider name into `resolveForSkill(skill, provider, model)`
* directly. This field is for cases where the registry is composed
* far from the agent (test fixtures, design-time inspectors).
*
* Match the provider's `name` field — `'anthropic'`, `'openai'`,
* `'mock'`, etc.
*/
readonly providerHint?: string;
}
export declare class SkillRegistry {
private readonly skills;
private readonly opts;
/**
* Construct an empty registry. Optional `{ surfaceMode, providerHint }`
* fields set registry-level defaults; absent both, the registry is a
* pure container (the v2.4 surface).
*/
constructor(opts?: SkillRegistryOptions);
/** Registry-level default `surfaceMode`, or `undefined` if unset. */
get surfaceMode(): SurfaceMode | undefined;
/** Registry-level provider hint, or `undefined` if unset. */
get providerHint(): string | undefined;
/**
* Register a skill. Throws if `skill.flavor !== 'skill'` or if a
* skill with the same id is already registered (use `.replace(...)`
* to overwrite intentionally).
*/
register(skill: Injection): this;
/** Replace an existing skill by id. Throws if id is not registered. */
replace(id: string, skill: Injection): this;
/** Remove a skill by id. No-op if not registered. */
unregister(id: string): this;
/** Look up by id. Returns undefined if not registered. */
get(id: string): Injection | undefined;
/** True iff a skill with the given id is registered. */
has(id: string): boolean;
/** All registered skills. Order matches registration order. */
list(): readonly Injection[];
/** Number of registered skills. */
get size(): number;
/** Drop all registrations. */
clear(): void;
/**
* Materialize the LLM-facing skill discovery tools from the current
* registry contents. Returns `{ listSkills, readSkill }`:
*
* - `list_skills` — no-arg tool the LLM calls to enumerate
* `{ id, description }` for every registered skill. Lets the
* LLM discover skills without paying the prompt-token cost of
* a static catalog in the system prompt.
*
* - `read_skill({ id })` — activates the named skill for the
* NEXT iteration. The Agent's tool-calls subflow inspects this
* tool call by name and updates `scope.activatedInjectionIds`
* so the InjectionEngine on iter N+1 includes the skill in the
* active set (body lands in the system slot; gated tools land
* in the tools slot).
*
* Both entries are `undefined` when the registry is empty — filter
* before adding to a tool list:
*
* const { listSkills, readSkill } = registry.toTools();
* const tools = [listSkills, readSkill, ...other].filter(Boolean) as Tool[];
*
* Composes with `gatedTools` from `agentfootprint/providers`
* so PermissionPolicy can scope which roles see the skill discovery
* surface.
*
* @returns A `SkillToolPair` (`{ listSkills, readSkill }`).
*/
toTools(): SkillToolPair;
/**
* Resolve the effective `surfaceMode` for a skill, applying the
* cascade:
*
* 1. If the skill's own `metadata.surfaceMode` is concrete
* (`'system-prompt'` / `'tool-only'` / `'both'`), return it.
* Per-skill explicit choice always wins.
* 2. Else if the registry was constructed with a concrete
* `surfaceMode`, return that.
* 3. Else delegate to `resolveSurfaceMode(provider, model)` using
* the explicit `provider` arg (or `this.providerHint` if
* omitted). Falls back to `'tool-only'` when no provider is
* known.
*
* Callers pass the agent's provider + model to get the RECOMMENDED
* surface mode for a skill. Note this is a recommendation, not the
* delivery decision: body delivery compares the DECLARED
* `metadata.surfaceMode` string, so a skill left on `'auto'` is
* delivered as `'system-prompt'` regardless of what this returns.
*
* Throws if the skill is not registered (catches typos at the
* caller site rather than silently resolving against a stranger).
*
* @param skillOrId A registered Skill `Injection` OR its `id`.
* @param provider Provider name override (wins over `providerHint`).
* @param model Model name for the per-provider attention rule.
*/
resolveForSkill(skillOrId: Injection | string, provider?: string, model?: string): Exclude<SurfaceMode, 'auto'>;
}
//# sourceMappingURL=SkillRegistry.d.ts.map