runTask and client tools
runTask creates a task and drives it to a terminal status on its own, handling the client tool interrupt cycle: call the handler, send the result, continue.
Schema and handler in one place
Each tools item carries both the tool definition and its handler. The SDK builds the request’s client_tools for you.
const task = await client.runTask( { assistant_id: 1, input: [textInput("What's the weather in Moscow?")], }, { tools: [ { name: 'get_weather', description: 'Current weather in a city.', input_schema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'], }, // return a string, { content } or { error, reason } handler: async (args) => JSON.stringify({ city: args.city, temperature_c: 21 }), }, ], onStatus: (t) => console.log(t.status), }, );
Handler map
Alternatively, tools accepts a { name: handler } map — then the tool definitions
are taken from input.client_tools (useful when the schemas come from somewhere else).
await client.runTask( { assistant_id: 1, input: […], client_tools: [/* definitions */] }, { tools: { get_weather: async (args) => '…' } }, );
Handler result
| Return value | Meaning |
|---|---|
string | Success, the result body. |
{ content: string } | Success, explicit form. |
{ error: string, reason?: string } | Tool error. |
runTask options
| Option | Purpose |
|---|---|
tools | ClientTool[] or a { name: handler } map. |
pollIntervalMs | Status polling interval. Default 1500. |
timeoutMs | Overall timeout for the whole run. |
maxRounds | Guard against an endless interrupt cycle. Default 10. |
onStatus | Callback on every poll. |
onMissingTool | Fallback when there’s no handler for the called tool. |
signal | AbortSignal to cancel the run. |
tools has no handler for the called tool, MissingToolHandlerError is thrown —
or onMissingTool is called, if you set it.
If the run breaks off
runTask drives the cycle to a terminal status on its own, but if a handler throws (or
maxRounds kicks in), the task stays interrupted — and keeps occupying a slot in
the concurrent task limit. Cancel it in catch:
try { await client.runTask(input, { tools }); } catch (err) { await client.cancelInterruptedTasks({ reason: 'Handler crashed' }); throw err; }
For a single task — cancelTask(uuid, { reason }). Details on both endpoints are in
Client tools.