Skip to content

Allow non-chat Think agent tools to complete#1483

Draft
whoiskatrin wants to merge 2 commits intomainfrom
fix-1482-agent-tool-non-chat-completion
Draft

Allow non-chat Think agent tools to complete#1483
whoiskatrin wants to merge 2 commits intomainfrom
fix-1482-agent-tool-non-chat-completion

Conversation

@whoiskatrin
Copy link
Copy Markdown
Contributor

@whoiskatrin whoiskatrin commented May 8, 2026

Summary

Fixes #1482.

Think agent-tool children previously treated "completed" as "the child produced assistant text after the run started." That made chat-like helpers work, but forced workflow/tool-step agents to emit sentinel text just to avoid an error terminal state.

This PR separates the agent-tool concerns:

  • execution: whether the Think turn completed, errored, or aborted
  • observation: streamed child chunks retained for UI/drill-in/replay
  • result synthesis: the output and summary returned to the parent

A Think child agent-tool run can now complete successfully without emitting assistant text. Assistant text remains the default summary for chat-like helpers, while non-chat children can provide structured output via getAgentToolOutput() and customize display text with getAgentToolSummary().

Follow-up: isServerStreaming stuck after reconnect

After the initial fix, @uuouter noted that useAgentChat().isServerStreaming could sometimes stay true after reconnect / finish.

The issue was a race between two resume paths in useAgentChat:

  1. The client receives cf_agent_stream_resuming before the AI SDK transport is awaiting resume.
  2. useAgentChat takes the fallback observer path, marks the stream as observed, and sets isServerStreaming to true.
  3. The AI SDK resumeStream() / transport path later starts awaiting the same stream id.
  4. A duplicate cf_agent_stream_resuming for that same id is handled by the transport, which adds the id to localRequestIdsRef.
  5. The terminal cf_agent_use_chat_response { done: true } then goes through the transport-owned/local-request branch.
  6. That branch cleaned up local request ids, but did not clear the earlier fallback observer state, leaving isServerStreaming stuck true.

This PR now clears fallback observer state when a terminal local-request response belongs to the same stream id.

Changes

  • Stop marking Think child agent-tool runs as error solely because no assistant text was emitted.
  • Add protected getAgentToolSummary(runId, output) as the summary hook paired with existing getAgentToolOutput(runId).
  • Persist Think child agent-tool output in cf_agent_tool_child_runs.output_json so completed output survives later inspection.
  • Add a migration for existing Think child agent-tool run tables.
  • Add regression coverage for:
    • chat-like agent-tool summary from assistant text
    • non-chat agent-tool completion with no text chunks
    • structured output persistence after the output hook no longer returns a value
    • existing error cleanup behavior
  • Fix useAgentChat().isServerStreaming cleanup when a stream first enters the fallback resume observer path and later becomes transport-owned.
  • Add React regression coverage for that resume ownership handoff.
  • Document the non-chat Think agent-tool pattern in docs/agent-tools.md and update the design doc.
  • Add a patch changeset for @cloudflare/think.

Testing

cd packages/think && npm run test -- src/tests/agent-tools.test.ts
cd packages/ai-chat && npx vitest --run --project react src/react-tests/use-agent-chat.test.tsx --testNamePattern "fallback-observed stream later becomes transport-owned"
cd packages/ai-chat && npx vitest --run --project react src/react-tests/use-agent-chat.test.tsx --testNamePattern "isServerStreaming"
npm run check

npm run check completes successfully. It still prints existing sherif warnings for package-less workspace directories, unrelated to this change.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 8, 2026

🦋 Changeset detected

Latest commit: a0dcd20

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/think Patch

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 8, 2026

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@1483

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@1483

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@1483

hono-agents

npm i https://pkg.pr.new/hono-agents@1483

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@1483

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@1483

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@1483

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@1483

commit: a0dcd20

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

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.

agentTool completion status for non-chat

1 participant