Skip to content

agents: poll tool tasks in the Python Claude Agent SDK adapter - #1801

Merged
longquanzheng merged 2 commits into
mainfrom
agents-python-claude-tool-tasks
Nov 13, 2026
Merged

longquanzheng merged 2 commits into
mainfrom
agents-python-claude-tool-tasks

Conversation

@longquanzheng

Copy link
Copy Markdown
Contributor

Summary

The Python Claude Agent SDK runner gains poll_tool_task and cancel_tool_task, routed to the ToolSource that built the call, exactly as execute_deferred_tool_call routes. The session core then reports supports_tool_tasks as true, so a ToolSource tool may return ToolTaskStarted; the session polls it in PollToolTask Steps and hands the final output to the resumed Claude session as the tool's result.

Why

An application wants a ToolSource tool that waits for an external event (for example a human reply) without a separate polling Flow. The built-in loop runner and pi already poll tool tasks; the Claude Agent SDK adapter recorded a started task as a call without a poller. The TypeScript adapter needs a public type change and waits for an owner decision.

Behavior change

McpToolSource, seeing supports_tool_tasks true, now hands Streamable HTTP server tasks to the session to poll instead of finishing them inside the tool Step.

Testing

  • adapter: ruff check, ruff format --check, mypy, pytest (96 passed, dexcli 1.47.3).
  • New tests/test_tool_tasks.py: pending twice then output reaches the resumed session; poll ToolExecutionError records failed; cancel_turn calls the source's cancel_tool_task once and the session still answers afterwards.

…urces

ClaudeAgentRunner implements poll_tool_task and cancel_tool_task. Each
routes the stored call to the tool source that built it, unwraps the
source's own reference, and passes the record on. The session now sets
supports_tool_tasks for this runner, so a source call that returns
ToolTaskStarted is polled on a Timer and its result reaches the resumed
Claude session; cancel_turn cancels the task through the source.
McpToolSource marks the heartbeat checkpoint of a task it hands to the
session with mcp_task_polled_by_session, as the TypeScript source does.
A retried CallTool attempt hands a saved task to the session only when
the marker is set; a task saved by an in-Step poll keeps polling in the
tool Step and is sent again with the same idempotency key when lost.

The Claude adapter's tool task docs move to 0.6.6, the cancel docstring
follows the CancelToolTask order, and the tests check that the stored
transcript answers every tool_use once and cover a source without
cancel_tool_task.
@longquanzheng
longquanzheng merged commit 12538b4 into main Nov 13, 2026
26 checks passed
@longquanzheng
longquanzheng deleted the agents-python-claude-tool-tasks branch November 13, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant