PAIPAI

runTool()

Execute one tool with no model, no HTTP, no thread runtime.

import { runTool } from "@pai/test-utils";

const result = await runTool(searchDocs, {
  input: { query: "tenancy" },
  context: { workspaceId: "ws_1", docs: fakeDocs },
});
expect(result.expectOutput().hits[0]?.title).toBe("Identity");

Import

import { runTool } from "@pai/test-utils";

Signature

function runTool(tool, options: {
  input;
  context?;
  capabilities?;
  signal?;
  threadId?;
  agentId?;
}): Promise<RunToolHandle>;

Parameters

tool: ToolDefinition

options: object

input: parsed inputSchema

context?: parsed contextSchema

capabilities?: object

A facade for each capability the tool declares, keyed as its capabilities declares them (sandbox for sandbox tools): required when the tool declares any, and a type error otherwise. For the sandbox, use createInMemorySandbox().

signal?: AbortSignal

threadId?: string

agentId?: string

Returns

A RunToolHandle.

Outcome checks and resume. The handle also has status, data, attempts, suspendHistory, and union fields output / error / suspend.

expectOutput: () => output

Throws if the tool did not return.

expectSuspended: () => { name, input }

Throws if the tool is not waiting.

expectFailed: () => { code, message, retryable? }

Deliberate ctx.fail. { code: "tool_failed", message }.

expectThrew: () => unknown

Raw exception.

expectCancelled: () => unknown

resume: (name, payload) => Promise<RunToolHandle>

dataWrites: Array

agentRuns: Array

Delegated ctx.agents runs.

ctx.fail("…") → expectFailed() is { code: "tool_failed", message }. Nested tools maps need createTestRuntime().

Examples

Suspend and resume

const waiting = await runTool(publishPost, {
  input: { draftId: "draft_1" },
  context: { drafts: fakeDrafts },
});

expect(waiting.expectSuspended().name).toBe("approve");

const done = await waiting.resume("approve", { approved: true });
expect(done.expectOutput()).toEqual({ published: true });

Fail vs throw

const failed = await runTool(getRecord, {
  input: { id: "missing" },
  context: { records: fakeRecords },
});
expect(failed.expectFailed()).toEqual({
  code: "tool_failed",
  message: "No record missing.",
});

const threw = await runTool(getRecord, {
  input: { id: "x" },
  context: { records: explodingRecords },
});
expect(threw.expectThrew()).toBeInstanceOf(DatabaseDownError);

Cancellation

const controller = new AbortController();
const pending = runTool(slowSearch, {
  input: { query: "tenancy" },
  context: { docs: fakeDocs },
  signal: controller.signal,
});
controller.abort();
expect((await pending).expectCancelled()).toBeDefined();

Learn more

On this page