Skip to content

Tools

defineTool turns a ToolConfig into a ready Tool. The common configuration uses a familiar name, description, strict input contract, effect, and execute function.

ts
import { defineTool, type ToolInput } from "@geekist/llm-core";

type SearchInput = {
  query: string;
};

const searchInput: ToolInput<SearchInput> = {
  schema: {
    type: "object",
    additionalProperties: false,
    required: ["query"],
    properties: { query: { type: "string" } },
  },
  validate: (value) =>
    typeof value === "object" &&
    value !== null &&
    !Array.isArray(value) &&
    Object.keys(value).length === 1 &&
    typeof value.query === "string"
      ? { valid: true }
      : { valid: false, issues: [{ path: "query", code: "required" }] },
};

const search = defineTool({
  name: "search",
  description: "Search the knowledge base.",
  input: searchInput,
  effect: "read-only",
  execute: ({ query }: SearchInput) => ({ hits: [`Result for ${query}`] }),
});

void search;

The facade snapshots its schema, validates every call without coercion, and keeps registration and execution provenance out of ordinary application code. A meaningful effect supplied as a short class name is rejected because its targets must be explicit.

Runtime extensions

Runtime and control implementers import from @geekist/llm-core/tools/runtime:

ContractResponsibility
ToolDefinitionPortable identity, schema, effects, and execution semantics
ExecutableToolProvenanced runtime tool that validates before execution
ToolExecutionResultPortable succeeded or failed execution result
ToolExecutionFailureSafe failure code, message, and retryability
defineToolDefinitionValidate and freeze a portable runtime definition
createExecutableToolJoin a definition, strict validator, and executor

The exact ExecutableTool returned by createExecutableTool carries runtime provenance. Shaped objects, casts, spreads, and clones do not.

Actions and effects

bindAction turns a tool call and definition into a canonical ActionDocument. actionDigest binds policy, approval, and receipt decisions to that exact action. If arguments or effect targets change, the digest changes.

Effect classMeaning
read-onlyObserves without changing a meaningful external resource
reversibleChanges state and has an explicit compensation path
external-writeChanges a resource outside the current process
destructiveIrreversibly deletes or damages meaningful state
privilegedRequires elevated authority

Effect class describes operational risk. Idempotency remains a separate execution guarantee.

What the action digest binds

actionDigest requires an ActionDigestPort to compute HMAC-SHA-256 over the UTF-8 bytes of the canonical action document. The port resolves an opaque, rotation-capable secret reference inside the supplied security domain. The returned value is the 43-character unpadded base64url encoding of the 32-byte digest.

IncludedDeliberately excluded
Tool ID, version, and input-schema digestRun, step, tool-call, and correlation IDs
Effect class and exact targetsTrace and observability identity
Tenant, principal, and delegation authority presentIdempotency keys and attempt counters
Execution and idempotency semanticsPolicy or approval decisions
Strict normalized argumentsReceipt lifecycle and timestamps
Credentials, provider clients, and native payloads

A tool does not grant itself authority. Route meaningful effects through controlled execution so policy, approval, receipts, and recovery apply.