Skip to main content
Give any single tool call a hard deadline, cancel a batch mid-flight with a token, and read a discriminated error_kind instead of an opaque error string — so your agent can decide to retry, switch tools, or abort.
Backward compatible. All new parameters are optional. With no timeout_ms and no cancel_token, execution delegates straight to the tool body — behaviour is unchanged.

Quick Start

1

Add a hard deadline

Pass timeout_ms (milliseconds) to execute_batch. A tool that runs longer is abandoned on a dedicated worker and returns a typed timeout result — the turn never hangs.
2

Add a cancel token

Pass any threading.Event-like token. Signal it from another thread to short-circuit pending calls with a typed cancelled result.
The token is duck-typed: threading.Event (.is_set()) and InterruptController-like tokens (.is_cancelled / .cancelled) both work — no concrete import required.
3

Handle structured errors

Pattern-match on error_kind and read structured_error for a discriminated payload:

How It Works

Because Python threads can’t be force-killed, a timed-out tool’s worker is abandoned (not joined) and a typed result is returned immediately — the turn keeps moving. Both executors forward timeout_ms and cancel_token:

error_kind Reference

ToolResult.error_kind is a discriminated tag; ToolResult.structured_error is None on success and a discriminated dict on failure.

Timeout, Cancel, or Both?

ToolExecutionConfig.timeout_ms is now consumed by the executor, so a configured default flows through to execute_batch without per-call wiring.
ParallelToolCallExecutor enforces the same per-tool timeout inside each worker, so one hung tool resolves to a typed timeout result instead of blocking collection of the others.

Parallel Tool Calls

Run batched tool calls concurrently

Tool Progress

Stream incremental progress from slow tools

Deferred Tools

Hand back long-running work without blocking

Tools Overview

Build and register agent tools