Add retained streaming agent tools#1421
Merged
threepointone merged 8 commits intomainfrom Apr 30, 2026
Merged
Conversation
Introduce first-class agent tools for running chat-capable Think sub-agents from a parent agent. This adds the parent run registry, event replay, cleanup, cancellation wiring, the AI SDK `agentTool` wrapper, React event aggregation, and the Think child adapter needed to stream retained child timelines through the parent connection. Rewrite the agents-as-tools example to consume the public APIs instead of the old helper-event prototype, and refresh docs, READMEs, design notes, tests, and release metadata so the feature is discoverable as the supported agent tools surface. Made-with: Cursor
Extend the agent-tool child adapter contract to AIChatAgent so existing chat agents can run as retained, streaming tools with durable inspection, replay, and cancellation. Also update the shared live-tail transport for Durable Object RPC byte streams and document the headless client-tool limitation for follow-up work. Made-with: Cursor
Persist structured agent-tool outputs, make AIChatAgent stream errors terminal, and expand cancellation/idempotency coverage so retained runs behave consistently across retries and replays. Refresh the docs and schema-version tests to reflect AIChatAgent support and the new parent registry column. Made-with: Cursor
🦋 Changeset detectedLatest commit: 5ab3181 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
Clean up parent abort listeners after completed agent-tool runs and avoid acquiring stream readers when forwarding starts from an already-aborted signal. Add regression coverage for both edge cases so future cancellation changes preserve the resource cleanup behavior. Made-with: Cursor
Add expectRootKeepAliveRefCount helper that polls agent.getRootKeepAliveRefCount (up to 20 attempts with a short delay) and use it in sub-agent tests instead of ad-hoc setTimeout waits. This replaces fragile fixed delays with a deterministic polling assert to reduce test flakiness in packages/agents/src/tests/sub-agent.test.ts.
Drop malformed or shape-invalid NDJSON frames during agent-tool stream forwarding so a corrupted display chunk does not fail an otherwise completed child run. Add regression coverage for the byte-stream forwarding path. Made-with: Cursor
Add a unit test (packages/think/src/tests/agent-tools.test.ts) that verifies in-memory agent-tool bookkeeping is cleared after a run completes. Extend ThinkTestAgent with helpers to seed a last-error for a run and to inspect map sizes (seedAgentToolLastErrorForTest, getAgentToolCleanupMapSizesForTest). Fix cleanup logic in think.ts to remove entries from _agentToolLastErrors and _agentToolPreTurnAssistantIds when an agent-tool run is torn down to avoid retained in-memory state.
Introduce AgentToolInspection and ThinkAgentToolTestStub types and tighten test helpers' signatures. freshAgent now returns a Promise<ThinkAgentToolTestStub> (with a cast from getAgentByName) and waitForAgentToolRun accepts the stub and returns AgentToolInspection. These changes improve TypeScript safety for agent tool tests and make available explicit method shapes used in the tests (inspectAgentToolRun, seedAgentToolLastErrorForTest, startAgentToolRun, getAgentToolCleanupMapSizesForTest).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
runAgentTool(),agentTool(), retained parent run registry, lifecycle/chunk event protocol, React event reducer/hook, and cleanup/replay helpers.@cloudflare/thinkandAIChatAgent, including streaming live-tail forwarding, cancellation, durable inspection, structured output persistence, and terminal error handling.examples/agents-as-toolsto use the framework APIs, and update docs, READMEs, design notes, WIP history, and the changeset for the shipped Agent Tools feature.Details
This PR promotes the previous agents-as-tools prototype into framework support. Parent agents now record retained runs in
cf_agent_tool_runs, stream childUIMessageChunkbodies asagent-tool-eventmessages, and allow clients to replay or render child timelines viauseAgentToolEvents().Think children implement the adapter through their existing session-backed chat turn machinery. AIChatAgent children run headlessly through
saveMessages(), with override hooks forformatAgentToolInput(),getAgentToolOutput(), andgetAgentToolSummary(). Server-side tools work in those runs; browser-provided client tools remain a follow-up design issue: #1420.The branch also hardens edge cases found during review: structured output is persisted for idempotent terminal reads, AIChatAgent stream errors become failed agent-tool runs, parent aborts are covered, reducer state creation avoids shared mutable empty state, and stale Think-only docs were updated.
Test plan
npm run test:workers -w @cloudflare/ai-chat -- --run src/tests/agent-tools.test.tsnpm run test -w agents -- src/tests/schema-and-state-optimization.test.tsnpm run build -w agentsnpm run build -w @cloudflare/ai-chatnpm run typechecknpm run checkMade with Cursor