Class EmergentToolRegistry

Constructors

Methods

  • Idempotent schema readiness guard.

    Ensures ensureSchema() is called exactly once and all subsequent callers await the same in-flight promise. This prevents the race condition where concurrent DB operations start before DDL statements finish.

    Returns Promise<void>

    A promise that resolves when the schema is ready.

  • Initialize the database schema for emergent tool persistence.

    Creates the agentos_emergent_tools, agentos_emergent_audit_log, agentos_emergent_tool_state and agentos_emergent_effects tables along with their indexes. Safe to call multiple times — all statements use CREATE TABLE IF NOT EXISTS / CREATE INDEX IF NOT EXISTS.

    This method is a no-op when no storage adapter was provided.

    Returns Promise<void>

    Throws

    If the storage adapter's exec or run method rejects.

  • Register a new emergent tool at the given tier.

    Session-tier tools are stored in the in-memory session map and mirrored to SQLite when available. Agent and shared tier tools are stored in the persisted map (and written to SQLite when a storage adapter is available).

    Parameters

    • tool: EmergentTool

      The emergent tool to register. Must have a unique id.

    • tier: ToolTier

      The tier to register the tool at. The tool's tier property is updated to match.

    Returns void

    Throws

    If the maximum tool count for the target tier is exceeded (checked against maxSessionTools or maxAgentTools from config).

    Throws

    If a tool with the same ID is already registered.

  • Record a tool's state, awaiting the write.

    options.request left out leaves the stored request alone: a new row stores none, and an existing row's request_json is not named by the update, so a request this process could not read (one a newer release wrote, say) is still there afterwards. A request writes it; null clears it.

    options.setBy records who set the state ('host' when left out). The library re-checks only its own suspensions at the next load; a host's stays until the host clears it, whatever words its reason uses.

    Writes for one tool run in call order, one after another. The isActive convention property of a tool held in memory follows the state.

    A restriction (suspended, demoted) is held in memory at call time, so the running process honours it whatever its write does. A reactivation (active) is held only once both writes have succeeded, and only when no other state change arrived while they ran: a suspension or demotion made meanwhile is the newer word, it stays, and this call returns that record instead of its own.

    options.ifRow makes the write conditional: an existing row is changed only while its state, setter and time are still the ones given, and 'absent' lets the write create a row but never change one. The loader uses it for its active write, so a restriction another process stored after the row was read is never written over; a refused write returns the row's own record, and a restriction read that way is held here as well. Every write, conditional or not, reads the row back after it: a state another process stored meanwhile is what is returned and held, and a tool another process removed reads as demoted with the reason removed.

    options.yieldToHost makes the write give way to the host's word: a row that holds a host's suspension, or a demotion, is not changed, and its record is returned and held instead; so is an active row whose tool row the host turned off with its own SQL (is_active = 0 with the mark clear), which the caller records as the host's demotion. The library's suspensions from a run or a promotion check use it, so they never replace a restriction a host set, in this process or in another.

    Parameters

    • toolId: string
    • state: ToolState
    • reason: null | string
    • options: {
          request?: null | StoredRequest;
          setBy?: StateSetter;
          ifRow?: {
              at: number;
              state: ToolState;
              setBy: StateSetter;
          } | "absent";
          yieldToHost?: boolean;
      } = {}

    Returns Promise<ToolStateRecord>

    the record now in force for the tool.

    Throws

    If the storage adapter rejects.

  • Whether a restriction this process requested for a tool may be missing from a row read that began at readAt (a beginRead point): its write is still queued or running, or settled after the read began, or it is a host's restriction whose write failed. A held restriction for which none of these is true is older than the row the read saw, whatever the clocks of the processes that wrote them say: the row decides.

    Parameters

    • toolId: string
    • readAt: number

    Returns boolean

  • Finish a state write whose flag write did not: the legacy flag from the state row, then the row's mark cleared, under the record the row holds so a newer write's mark is left alone. The loader calls it for a row whose mark is pending, before anything about the row is decided.

    Parameters

    • toolId: string
    • record: Pick<ToolStateRecord, "at" | "state" | "setBy" | "writeId">

    Returns Promise<void>

  • Suspend a tool on the host's word: an awaited write of its state and of is_active = 0, recorded as the host's, so no load lifts it whatever the reason says; only a reactivation does. Usage statistics are left alone. The caller unregisters the executable.

    Parameters

    • toolId: string
    • reason: string

    Returns Promise<void>

    Throws

    If the tool is unknown or the write fails.

  • Drop a tool from memory without touching its rows: for a load whose registration with the host failed, so the row is there for the next load and nothing here claims a tool the executor does not run; and for a state held for a tool that has neither a row nor an object here any more.

    Parameters

    • toolId: string

    Returns void

  • A number that grows on every change to the tool in this process (a registration, an adoption, a row write, a removal); 0 for a tool not seen. Two equal readings mean nothing changed in between.

    Parameters

    • toolId: string

    Returns number

  • The writer of effect records over this registry's storage, or undefined without a storage adapter. The schema is made ready before its first write.

    Parameters

    • options: {
          content: "full" | "digest";
          retainDays?: number;
      }
      • content: "full" | "digest"
      • Optional retainDays?: number

    Returns undefined | EffectsStore

  • Write a tool's row from the object given, awaited. For a host that hydrates a tool from its own store through syncPersistedTool and has no row for it yet; a tool that has a row is loaded from the row, never rewritten by a load.

    Parameters

    Returns Promise<void>

  • Take a tool read from storage into memory without rewriting its row. upsert re-serialises the source; a loaded tool must keep the row it has.

    Parameters

    • tool: EmergentTool
    • record: ToolStateRecord
    • Optional ifUnchangedSince: number

      The point the caller's read started at (beginRead), or a generation reading. The adoption is refused when the tool changed in this process after it, or a removal or a rewrite of the tool's rows is still pending: the row the caller holds may then be one that is gone or about to change.

    Returns boolean

  • The stored rows of the given tiers, in creation order, with their state rows: every shared row, the agent rows of scope.agentId and the session rows of scope.sessionId. A tier named without its selector contributes no rows; the engine refuses such a call before it gets here.

    Parameters

    • tiers: readonly ToolTier[]
    • scope: {
          agentId?: string;
          sessionId?: string;
      } = {}
      • Optional agentId?: string
      • Optional sessionId?: string

    Returns Promise<PersistedToolRow[]>

  • Hold a stored state for a tool this process holds no object for: a load that finds a restriction already stored on a row it does not activate takes it in here, so listStates carries it (a registration of a composition's missing step tool re-checks the composition from it). Nothing is written.

    Parameters

    Returns void

  • Record the session a stored session-tier tool belongs to (its row's created_by_session), before a state is held for it here: a load's admission, or a host's restriction of a tool this process never loaded. cleanupSession then lets go of a state held for it without the tool, and deletes its rows.

    Parameters

    • toolId: string
    • sessionId: string

    Returns void

  • A tool's state as its row reads now, or undefined; what this process holds is not consulted. The loader reads it before adopting a row it has nothing to write for, since a restriction another process stored after the row was read is the newer word.

    Parameters

    • toolId: string

    Returns Promise<undefined | ToolStateRecord>

  • Replace the in-memory copy of a tool and mirror it to storage.

    The row is rewritten from the object given, in the tool's write queue. To bring stored tools back after a restart, call the engine's loadPersistedTools, which reads each row, checks it and never rewrites it. A tool whose state this process does not hold keeps the is_active its row has.

    Parameters

    Returns void

  • Get all tools registered at a specific tier, optionally filtered by scope.

    Parameters

    • tier: ToolTier

      The tier to query ('session', 'agent', or 'shared').

    • Optional scope: {
          sessionId?: string;
          agentId?: string;
      }

      Optional scope filter. When provided, results are narrowed:

      • sessionId: Match tools whose source string contains the session ID.
      • agentId: Match tools whose createdBy equals the agent ID.
      • Optional sessionId?: string
      • Optional agentId?: string

    Returns EmergentTool[]

    An array of matching tools (may be empty).

  • Record a tool invocation, updating rolling usage statistics.

    Updates the tool's ToolUsageStats in place:

    • Increments totalUses.
    • Increments successCount or failureCount based on the success flag.
    • Recalculates avgExecutionTimeMs as a running average.
    • Recalculates confidenceScore as successCount / totalUses.
    • Sets lastUsedAt to the current ISO-8601 timestamp.

    Parameters

    • toolId: string

      The ID of the tool that was invoked.

    • _input: unknown

      The input arguments passed to the tool (logged for audit).

    • _output: unknown

      The output returned by the tool (logged for audit).

    • success: boolean

      Whether the invocation completed successfully.

    • executionTimeMs: number

      Wall-clock execution time in milliseconds.

    Returns boolean

    false when the tool is suspended or demoted and nothing was recorded.

    Throws

    If no tool with the given ID is registered.

  • Promote a tool to a higher lifecycle tier.

    Moves the tool from its current tier to targetTier. If the tool was at session tier, it is removed from the session map and added to the persisted map. If a storage adapter is available and the target tier is agent or shared, the tool is persisted to the database. The promotion is a change point, and its row write runs in the tool's write queue: an admission that read the row before it reads the row again, and a removal that comes after it deletes the promoted row.

    Parameters

    • toolId: string

      The ID of the tool to promote.

    • targetTier: ToolTier

      The target tier to promote to. Must be strictly higher than the tool's current tier.

    • Optional approvedBy: string

      Optional identifier of the human or system entity that approved the promotion.

    Returns Promise<void>

    Throws

    If the tool is not found.

    Throws

    If targetTier is not higher than the tool's current tier.

  • Demote or deactivate a tool.

    Marks the tool as inactive by setting a sentinel on its usage stats (confidenceScore set to 0), records the demoted state and logs the demotion event with a reason.

    Inactive tools are still retrievable via get() but should be filtered out by callers when building tool lists for the LLM.

    Returns a promise for the state write, which rejects when the write fails; await it when the demotion must be durable. An un-awaited call cannot become an unhandled rejection. The in-memory effects have happened by the time this returns.

    Parameters

    • toolId: string

      The ID of the tool to demote.

    • reason: string

      Human-readable explanation for why the tool is being demoted.

    Returns Promise<void>

    Throws

    If the tool is not found (thrown synchronously).

  • Remove all session-tier tools associated with a specific session.

    Iterates the session map and deletes every tool whose source names the given session; the rows go after the tool's queued writes. Logs a cleanup audit event for each removed tool. The session's stored tools whose state this process holds without the tool (a load admitted them suspended or demoted, or the host restricted one it never loaded) go too: the state before this returns, so no registration from then on re-checks one and a re-check already under way does not adopt it, and the rows after their queued writes, while they are still the session's. Rows of the session this process never admitted or restricted are left to the process that holds them.

    Parameters

    • sessionId: string

      The session identifier to match against tool source strings.

    Returns number

    The number of live tools removed.