Skip to content

test(tutorials): poll task state instead of a fixed 1s sleep - #548

Merged
danielmillerp merged 2 commits into
mainfrom
dm/poll-streaming-state
Oct 9, 2026
Merged

danielmillerp merged 2 commits into
mainfrom
dm/poll-streaming-state

Conversation

@danielmillerp

@danielmillerp danielmillerp commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

What

The async base tutorials 010_multiturn and 020_streaming now poll the task state instead of sleeping a fixed second before asserting it.

Why

Each test sends an event, waits for the agent's reply, sleeps 1s, then asserts the task state holds 3 messages. The agent sends its reply first and persists the turn to state afterwards. When the model call is slow, the 1s read sees only the system message and the test fails with assert 1 == 3. This shows up as random red Agent Integration Tests on unrelated server PRs.

How

  • test_utils/async_utils.py: new wait_for_state_messages, which polls the state until it reaches the expected count or a 30s timeout, then returns the last read.
  • Both tutorials use it in place of the sleep-then-read blocks (4 call sites).

A state that never updates still fails, with its real length. The initial-state checks after task creation are unchanged.

Verification

  • Unit tests (tests/lib/test_tutorial_async_utils.py, new, 3 passed) against a fake client:
    • state written 0.3s after the reply → waits and returns 3 messages (a fixed sleep shorter than the write delay reads 1)
    • state never written → returns 1 message at the 0.3s deadline, so the caller's assert fails as before
    • state already written → returns on the first poll with no added delay
  • ruff check and pyright on the changed files pass. All 52 CI checks passed on the first push.
  • Not yet verified: a live run. The server repo's integration workflow runs the tests baked into the published tutorial images, so this change reaches it only after those images are rebuilt from this branch.

🤖 Generated with Claude Code

RetriggerConfidence Score: 5/5

The PR appears safe to merge; both earlier findings are addressed and no new issue was found in this PR’s changes.

Fix All in CursorFindings

  1. P2 Busy workers fail this test ▶
Fix with agent prompt
### Issue 1
tests/lib/test_tutorial_async_utils.py:undefined-67
If a busy worker wakes more than two seconds after this test starts, the wall-clock check fails even though `wait_for_state_messages` honored its deadline. The root suite runs tests in parallel, so this can add an unrelated red test to the suite this PR aims to make more reliable. Check the deadline without requiring a fast wake-up.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The 010_multiturn and 020_streaming tutorial tests now poll task state before checking for three messages, since an agent reply can arrive before the turn is saved.

  • Async tutorial checks wait for task messages to be saved.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Agent replies] --> B[Poll task state]
  B --> C{Three messages yet?}
  C -- Yes --> D[Check messages]
  C -- No, time remains --> B
  C -- No, deadline passed --> D
Loading

Reviews (5) · Last reviewed commit: "chore(tutorials): drop the unrelated uv...." · Reviewed by Greptile

Comment thread examples/tutorials/test_utils/async_utils.py
@danielmillerp
danielmillerp force-pushed the dm/poll-streaming-state branch from 51c83d3 to fb2fe3d Compare October 9, 2026 01:08
Comment thread tests/lib/test_tutorial_async_utils.py Outdated
messages = await wait_for_state_messages(client, "agent", "task", expected_count=3, timeout=0.3, sleep_interval=0.05)

assert len(messages) == 1
assert 0.3 <= time.monotonic() - start < 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Busy workers fail this test

If a busy worker wakes more than two seconds after this test starts, the wall-clock check fails even though wait_for_state_messages honored its deadline. The root suite runs tests in parallel, so this can add an unrelated red test to the suite this PR aims to make more reliable. Check the deadline without requiring a fast wake-up.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/lib/test_tutorial_async_utils.py
Line: 67

Comment:
**Busy workers fail this test**

If a busy worker wakes more than two seconds after this test starts, the wall-clock check fails even though `wait_for_state_messages` honored its deadline. The root suite runs tests in parallel, so this can add an unrelated red test to the suite this PR aims to make more reliable. Check the deadline without requiring a fast wake-up.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Claude Code Fix in Codex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. The upper wall-clock bound is gone. The test now asserts only that the helper kept polling until the deadline (elapsed >= timeout) and returned the 1-message state. A late wake on a busy worker can no longer fail it.

@danielmillerp
danielmillerp force-pushed the dm/poll-streaming-state branch from fb2fe3d to cffaa34 Compare October 9, 2026 01:14
danielmillerp and others added 2 commits October 8, 2026 22:13
The async base tutorials sent the agent's reply, slept 1s, then asserted the
task state held 3 messages. The agent persists the turn to state only after it
sends the reply, so a slow model call left the read seeing the previous turn
and failed with "assert 1 == 3".

Add wait_for_state_messages to test_utils, which polls the state until it
reaches the expected count or a 30s timeout, and use it in 010_multiturn and
020_streaming. A state that never updates still fails with its real length.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lock change only rewrote the SDK's own recorded version
(0.21.0 to 0.28.2), a side effect of a local uv run. The polling change
doesn't need it, and leaving it in risks a conflict with the next
release or reconcile commit that touches uv.lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@danielmillerp
danielmillerp force-pushed the dm/poll-streaming-state branch from 932cdb0 to 49ddd06 Compare October 9, 2026 02:13
@danielmillerp
danielmillerp merged commit 8a71db3 into main Oct 9, 2026
53 checks passed
@danielmillerp
danielmillerp deleted the dm/poll-streaming-state branch October 9, 2026 14:07
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