anthropics / anthropics/claude-agent-sdk-typescript

query() async iterator hangs after final tool_result on multi-turn WebSearch agents — never yields next assistant turn or result

Open
#333 0 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Shell
Stars
1.8k
Forks
226
PR merge metrics
No merged PRs in 30d

Description

## Summary

A WebSearch-enabled agent runs several healthy multi-turn rounds, then the `for await (… of query(…))` async iterator **stops advancing immediately after the SDK delivers the final `user`/`tool_result` message**. No subsequent `assistant` turn, no `result` message, no thrown error — the iterator simply goes silent indefinitely.

## Environment

- `@anthropic-ai/claude-agent-sdk` **0.2.132**
- Subscription auth (no `ANTHROPIC_API_KEY`)
- One `query()` call per fresh Node subprocess (we spawn a clean process per agent)
- `options`: `allowedTools: ["WebSearch"]`, `disallowedTools` for everything else, `maxTurns: 25`, `outputFormat: { type: "json_schema", schema }`, `settingSources: []`, `agents: {}`, `mcpServers: {}`

## Trace evidence

We instrumented the loop to log every yielded message with elapsed/gap timing. One representative run (ms since `query()` start):

```
query_started t=0
sdk_message type=system subtype=init t=4974
sdk_message type=rate_limit_event t=5944
… 5 repeating rounds of [assistant ×5, user ×4] (multi-turn WebSearch) …
sdk_message type=assistant t=144593
sdk_message type=user t=149856 (tool_result)
sdk_message type=user t=150672 (tool_result)
sdk_message type=user t=150737 (tool_result)
sdk_message type=user t=150832 (tool_result) ← LAST yield
[no further messages — ~419s of total silence — process killed at t=600000]
```

~5 rounds of WebSearch complete successfully, so the tool itself works. The hang is specifically the **tool_result → next assistant turn** transition: after the final batch of `tool_result` (`user`) messages, the iterator never produces the next `assistant` turn, a `result`, or an error. One `rate_limit_event` appears early (t=5944ms); none precedes the stall.

## Reproduction

A single `query()` for one WebSearch-enabled agent with a research-heavy, no-evidence prompt (one that drives ~5+ rounds of web search) reproduces this reliably (~1/1 in our runs). It is not `maxTurns` exhaustion — that would yield a terminal `result`, not a silent hang. It is not the first WebSearch call — several succeed first.

## Expected vs actual

- **Expected:** after a `tool_result`, the iterator yields the next `assistant` turn, or a terminal `result`/error.
- **Actual:** the iterator goes silent and never settles; only an external timeout/kill ends it.

## Possibly related

- #289 (`query({resume})` drops tool_use/tool_result sequences when JSONL grows large)
- #114 (MCP responses don't reset `lastActivityTime` → excessive query duration)
- #300 (stream starvation in parallel sessions)

Happy to provide the full JSONL trace or a minimal repro harness if useful.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.