Skip to content

Tool call

The row a reply shows when the model calls one of your tools — its name, what it was asked, what it returned, and whether it is running, waiting for a person or done.

  • type: 'tool_call'
On this page
Open

When the model calls a tool, the reply gets a tool_call segment and the bubble draws it as a quiet row: the tool’s name and its status. Opening the row shows the input the model chose and the result your handler returned. The row is drawn for you; a tool registered with aparteGlobalConfig.registerTool() produces it during a turn without any code of yours.

Open

A call is pending while your handler runs, awaiting-approval when the tool is marked needsApproval and a person has to decide (see Tools and approval), then resolved, rejected, aborted or failed. Only the first two are still open.

Open

registerToolSummary(name, summary) adds one line after the tool’s name, so read_file reads read_file docs/release.md without opening the row. It returns plain text; the row, its states and its disclosure stay the library’s.

Open

registerToolRenderer(name, renderer) replaces the row for one tool. Return an element rather than an HTML string: the input and the result come from the model and your tool, so a string would have to escape every value it interpolates. Add an update() to patch the element when the result lands, instead of rebuilding it.

ts
import { aparteGlobalConfig } from '@aparte/core';

aparteGlobalConfig.registerTool(
  {
    name: 'get_weather',
    description: 'Current weather for a city.',
    inputSchema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] },
  },
  async (call) => ({ toolCallId: call.id, content: `Cloudy, 14 °C in ${call.input.city}.` }),
);

The client offers the tool to the model, runs the handler when it is called and draws the row for each call. Building a segment by hand, as these demos do, is for a reply your own code assembles.

AparteToolCallSegment, discriminated by type: 'tool_call'.

FieldTypeRequiredDescription
toolCallAparteToolCallyes
status'pending' | 'resolved' | 'aborted' | 'awaiting-approval' | 'rejected' | 'failed'yesawaiting-approval — paused for a human decision; rejected — the human (or a policy) declined to run it; aborted — stopped, timed out, or nothing could run it; failed — the handler threw, and result carries the crash’s one line. More
resultstring—
structuredResultunknown—The handler’s structuredContent, when it returned one — the value behind result’s prose.
deferred{ reason: 'approval' | 'external' | 'queued'; ticket?: string }—Set when a server loop (createAparteAgentHandler) suspended its run on this call: why it waits — a person’s decision (approval), a tool the page runs (external), or nothing but its turn (`queued More

status — awaiting-approval — paused for a human decision; rejected — the human (or a policy) declined to run it; aborted — stopped, timed out, or nothing could run it; failed — the handler threw, and result carries the crash’s one line.

deferred — Set when a server loop (createAparteAgentHandler) suspended its run on this call: why it waits — a person’s decision (approval), a tool the page runs (external), or nothing but its turn (queued) — and the server’s signed continuation. Saved with the conversation, so a reload can still answer it (AparteClient.resumeDeferred).

  • When there is an input or a result to show, the row is a native <details>: its summary opens with Enter or Space and announces whether it is expanded. With nothing behind it, it is a plain row and takes no tab stop.
  • The status is written in words (locale keys such as toolRunning, toolCompleted, toolFailed), not only shown as a colour or an icon.
  • Tools and approval — registering tools, what the row shows, and asking a person first.