Graphorin API reference v0.7.0
Graphorin API reference / @graphorin/tools
@graphorin/tools
Typed tool surface for the Graphorin framework.
@graphorin/tools ships the runtime building blocks every other @graphorin/* package above the persistence layer uses to declare, register, and execute tools the model can call:
tool({...})- typed factory for declaring a Zod-validated tool. Inference flows frominputSchema/outputSchemainto theexecute(input, ctx)callback so authors never repeat the input shape.createToolRegistry(...)- strategy-aware registry that hosts every registered tool. Supports the back-compatassertNoDuplicates()pure-detection signature AND the strategy-awareassertNoDuplicates(strategy, ctx)overload that resolves cross-source collisions through the'auto-prefix' | 'priority' | 'manual'strategies (with a first-party / trusted-skill > untrusted-skill > MCP precedence ladder).createToolExecutor(...)- runsTool[]invocations:- parallel-by-default dispatch with bounded concurrency (
maxParallelTools);executionMode: 'sequential'opts a tool out; - approval flow (
needsApprovalpredicate ⟶ blocking gate); - per-tool secrets ACL scoping via
@graphorin/security/secrets'swithChildToolSecretsContext; - sandbox-policy resolution via
@graphorin/security/sandbox'sresolveSandbox(...)plus an optionalsandboxResolverinjection point that the skill loader / agent runtime wires when sandbox-bundled code (skills, MCP-derived handlers) needs out-of-process execution (delegates toSandbox.run(...)); - memory-modification guard hook (
memoryGuardFactory+memoryRegionReader) - snapshot-before, verify-after, with the mismatch path emitting an audit row and thetool.executor.memory_guard.mismatch.total{toolName,tier}counter increment; - hard-kill cancellation with a configurable grace window for tools that ignore
ctx.signal(50 ms default; cancellation surfacesToolError({ kind: 'aborted' })andsetStatus('cancelled')on the span); - single-round tool repair via the operator-supplied repair hook;
- a recoverable-error envelope: every
ToolErrorcarriesrecoverable+ arecoveryHint(retry_later/check_input/try_alternative/report_to_user) rendered to the model under the error message; - transparent bounded retry of
rate_limitedoutcomes from pure / read-only / idempotency-keyed tools (defaultsmaxAttempts: 3,backoffMs: 250;ToolRateLimitError.retryAfterMswins; tune viacreateToolExecutor({ retry })); - per-execution
tool.executeAISpan emitted via the run's tracer with rich attributes (graphorin.tool.name,graphorin.tool.call_id,graphorin.tool.sandbox.kind,graphorin.tool.sandbox.forced,graphorin.tool.sandbox.no_network,graphorin.tool.sandbox.no_filesystem,graphorin.tool.memory_guard.tier,graphorin.tool.sensitivity,graphorin.tool.side_effect_class,graphorin.tool.streaming_hint,graphorin.tool.trust_class,graphorin.tool.duration_ms,graphorin.tool.result.contentpart.kind.<image|audio|file>,graphorin.tool.result.truncation.strategy,graphorin.tool.result.truncation.applied,graphorin.tool.result.max_tokens,graphorin.tool.inbound.sanitization.scan_duration_us,graphorin.tool.inbound.sanitization.policy,graphorin.tool.inbound.sanitization.patterns_hit_count); - per-execution audit rows + counter increments keyed under stable prefixes (
tool.executor.*,tool.classification.*,tool.collision.*,tool.inbound.sanitization.*,tool.result.*,tool.streaming.*,tool.preferred-model.*,tool.retrieval.*).
- parallel-by-default dispatch with bounded concurrency (
- Default spill writer - when no operator-supplied
SpillWriteris configured, the executor writes spill artifacts to<os.tmpdir()>/graphorin-spill/<runId>/<toolCallId>.<ext>with0600permissions and tier-aware sensitivity inheritance fromTool.sensitivity. Operators that need a sandbox-aware path ('worker-threads'/'isolated-vm'/'docker'tier filesystems) inject their own writer viacreateToolExecutor({ spill }). The framework scans the FULL body for imperative patterns once at spill time (W-156: a pattern split by aread_resultpage boundary evades the per-page strip pass in both halves) and hands the result to every writer asimperativePatternsPresent; a custom writer that does not persist the field loses only that read-side operator signal - the per-page untrusted-content envelope and producer-taint sidecar semantics are unaffected (same limitation class as ignoring the taint fields). - Inbound prompt-injection sanitization - five-policy pipeline (
'pass-through' | 'detect-and-flag' | 'detect-and-strip' | 'detect-and-wrap' | 'detect-and-strip-and-wrap') keyed off the per-tool trust class. Catalogue lives in@graphorin/observability/redaction/imperative-patterns(sibling to the PII / secrets catalogue used by the outbound exporter validators). OptionalfailClosed: trueopt-in surfaces hits asToolError({ kind: 'inbound_sanitization_blocked' })for regulated deployments. - Result truncation pipeline - four strategies (
'middle' | 'tail' | 'spill-to-file' | 'summarize') honouring per-toolmaxResultTokens(default16384;0disables with a one-time WARN). Trust-class auto-defaults:'tail'for built-incode_execution;'summarize'for built-inweb_search;'middle'everywhere else. Truncation annotations are bytes-stable AND calibrated to NOT match any imperative-pattern so the downstream sanitization scan is false-positive-free. - Streaming-tool execution - opt-in via
tool({ streamingHint: true, async execute(_input, ctx) { ctx.streamContent({ kind: 'text', text: 'chunk' }); ctx.reportProgress(1, 3); } }). The executor maintains a per-toolCallIdaggregation buffer; the assembled buffer becomes the canonicaloutputwhenexecutereturnsvoid. Event delivery to the sink is synchronous - there is no queue; thestreamingEventQueueDepthguard (default256) only trips on sink re-entrancy and drops the CURRENT (newest) event, counted intool.streaming.events.dropped.total. The aggregation buffer is byte-capped (streamingMaxBufferBytes, default 8 MiB): past the cap chunks keep streaming to subscribers but stop accumulating, dropped bytes are counted and the aggregator reportsbufferTruncatedso the assembled body is marked incomplete. - Side-effect classification -
sideEffectClass: 'pure' | 'read-only' | 'side-effecting' | 'external-stateful'REQUIRED on the public surface (with a v0.1 transition mode that emits a one-time WARN per tool name on missing classification and applies the conservative deferred default'side-effecting'). CompanionidempotencyKey?: (input, ctx) => stringcallback REQUIRED-by-WARN for'side-effecting' | 'external-stateful'tools - the framework never validates the determinism property; that is the operator's contract. - Per-tool model preferences -
preferredModel?: ModelHint | ModelSpecwith the cost-tier vocabulary'fast' | 'balanced' | 'smart'exported from@graphorin/core. The agent runtime (Phase 12) reads the per-tool hint at the per-step planner; an explicitModelSpecalways wins over the cost-tier vocabulary. - Tool retrieval at scale -
defer_loading?: booleanopt-in. The built-intool_search({ query, k? = 5 })(re-exported by@graphorin/tools/built-in) is auto-registered by the agent runtime when at least one tool is deferred; backed by the three-tier ranking chain (semantic via the agent's embedder ⟶ BM25 fallback ⟶ regex name-match final fallback). - Worked examples - optional
examples?: ToolExample[]per tool (bounded[1, 5]; overflow emits a one-time WARN). Each example'sinputandoutputis validated against the tool's schemas at registration; programming errors fail-fast.
Stable sub-paths
ts
// Builder + tool spec.
import { tool } from '@graphorin/tools/builder';
// Zod v3/v4 -> JSON Schema converter (what goes on the provider wire).
import { zodToJsonSchema, projectSchemaToJsonSchema } from '@graphorin/tools/schema';
// Strategy-aware registry.
import { createToolRegistry } from '@graphorin/tools/registry';
// Executor.
import { createToolExecutor } from '@graphorin/tools/executor';
// Streaming surface.
import { createStreamingChannel } from '@graphorin/tools/streaming';
// Inbound sanitization.
import { applyInboundSanitization } from '@graphorin/tools/inbound';
// Result envelope helpers + truncation pipeline.
import { truncateBody, toResultEnvelope } from '@graphorin/tools/result';
// Built-in tools (`tool_search`, ...).
import { createToolSearchTool } from '@graphorin/tools/built-in';
// Audit + counter registry.
import { onToolAudit, snapshotCounters } from '@graphorin/tools/audit';
// Typed errors.
import { DuplicateToolNameError } from '@graphorin/tools/errors';Hello-world
ts
import { tool, createToolRegistry, createToolExecutor } from '@graphorin/tools';
import { z } from 'zod';
const greet = tool({
name: 'greet',
description: 'Greet the user by name.',
inputSchema: z.object({ name: z.string() }),
outputSchema: z.object({ greeting: z.string() }),
sideEffectClass: 'pure',
async execute({ name }) {
return { greeting: `Hello, ${name}!` };
},
});
const registry = createToolRegistry();
registry.register(greet);
const executor = createToolExecutor({ registry });
const completed = await executor.executeBatch({
calls: [{ toolCallId: '1', toolName: 'greet', args: { name: 'world' } }],
runContext, // supplied by your agent runtime
stepNumber: 1,
});Dependencies
zod- required peer dependency. Used for input / output / example validation. v3 and v4 are both supported.@graphorin/core- typed contracts (Tool,ToolExecutionContext,ResolvedTool,ToolExample,ContentChunk,SideEffectClass,InboundSanitizationPolicy,TruncationStrategy,ToolTrustClass, theToolExecuteProgressEvent/ToolExecutePartialEventagent-event variants, …).@graphorin/security- sandbox policy resolver (resolveSandbox), per-tool secrets ACL plumbing (withChildToolSecretsContext,enforceSecretAcl).@graphorin/observability- imperative-pattern catalogue (@graphorin/observability/redaction/imperative-patterns).
License
MIT. Copyright © 2026 Oleksiy Stepurenko.
Project Graphorin · v0.7.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin
Modules
| Module | Description |
|---|---|
| @graphorin/tools - typed tool surface for the Graphorin framework. | |
| audit | Audit-event emitter + counter registry for @graphorin/tools. |
| builder | Tool builder surface for @graphorin/tools. |
| built-in | Built-in tools shipped with @graphorin/tools. |
| code-mode | Code-mode / programmatic tool calling (P1-2). Public surface: |
| errors | Typed error classes for @graphorin/tools. |
| executor | Tool executor surface for @graphorin/tools. |
| inbound | Inbound prompt-injection sanitization surface for @graphorin/tools. |
| package.json | - |
| registry | Strategy-aware tool registry surface for @graphorin/tools. |
| result | Tool result envelope helpers for @graphorin/tools - token counting, truncation pipeline (`'middle' |
| schema | Schema projection surface: the shared Zod-to-JSON-Schema converter used by the agent's toolToDefinition, the code-mode signature projection, and ToolSearchMatch (tools-01). |
| streaming | Streaming-tool execution surface for @graphorin/tools. |