Skip to content

test(aws-strands): bind the test servers to the address the probes dial - #2621

Merged
AlemTuzlak merged 1 commit into
mainfrom
claude/distracted-goodall-68fa01
Sep 3, 2026
Merged

test(aws-strands): bind the test servers to the address the probes dial#2621
AlemTuzlak merged 1 commit into
mainfrom
claude/distracted-goodall-68fa01

Conversation

@ranst91

@ranst91 ranst91 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

The flake

integrations/aws-strands/typescript/src/__tests__/cors.test.ts failed roughly one run in six when the machine was under load. The failure moved around between runs, which is why it read as several unrelated problems:

  • a CORS header with the wrong value, or absent entirely
  • agent.runs still 0 after a POST that returned a response
  • HTTPParserError: Response does not match the HTTP/1.1 protocol whose payload was {"type":"Tier1","version":"1.0"}, a body no route in this package emits
  • SocketError: other side closed with bytesWritten: 334, bytesRead: 0

All four are the same defect.

Root cause

app.listen(0) with no host binds the IPv6 wildcard (::). Every probe in these suites dials 127.0.0.1, an IPv4 address. Those are not the same port.

When an unrelated process already holds the IPv4 wildcard on the port number the kernel hands out, that process keeps receiving the loopback traffic and answers the probe. The test's own server never sees a connection, so it emits no connection event and its agent never runs. What the suite asserts on is whatever the stranger happened to reply.

lsof at the moment of failure, captured by a stress harness:

COMMAND   PID USER   FD   TYPE   DEVICE   SIZE/OFF NODE NAME
Spotify   855  ran  214u  IPv4   0xb8e...      0t0  TCP *:52655 (LISTEN)
node    38136  ran   13u  IPv6   0x649...      0t0  TCP *:52655 (LISTEN)

Two listeners on one port number, one per address family. The {"type":"Tier1","version":"1.0"} body in the parser error is that other process's local API answering, not anything this package serves.

Reproduced deliberately with a stand-in process holding the IPv4 wildcard, which isolates the mechanism from any particular application being installed:

--- unspecified host (previous harness behaviour) ---
our bind ok: {"address":"::","family":"IPv6","port":56613}
fetch 127.0.0.1:56613 -> {"type":"Tier1","version":"1.0"}   (our server saw request: false)

--- 127.0.0.1 host ---
our bind ok: {"address":"127.0.0.1","family":"IPv4","port":56616}
fetch 127.0.0.1:56616 -> {"whoami":"ours"}                  (our server saw request: true)

This also explains why no listen port was ever duplicated inside the test process, and why the collision rate tracks machine load: the more of the ephemeral range is churning, the likelier a test draws a number some other process is already sitting on.

The change

Pin the bind address to 127.0.0.1 in the shared transport harness and in the seven sibling suites that bound the same way. A specific bind takes precedence over a wildcard holder, so a probe now reaches its own app or nothing at all.

The harness self-test gains an assertion on the bind address, so dropping the host fails there rather than reappearing silently as a flake in an unrelated suite.

No behaviour under test changes: no assertion is weakened, no retry or timeout is added, and no runtime string, error code, or logged message is touched.

Verification

  • A stress rig cycling the real harness (bind, POST, /capabilities, preflight, close) failed 3 times in 2000 cycles before the change and ran 6000 cycles clean after it, both under ten busy cores.
  • 35 consecutive green runs of cors.test.ts under load, then 32 more after the self-test was added.
  • Full package suite green: 76 files, 1612 tests.
  • tsc --noEmit clean; Prettier clean on every changed file.

Unrelated to the documentation-contract work in #2620.

The CORS suite failed roughly one run in six under load, and the failure
moved around: a wrong header, an agent that never ran, an HTTP parse error
carrying a body no route in this package emits, a bare close with nothing
read. All four were the same defect.

`app.listen(0)` with no host binds the IPv6 wildcard, while every probe in
these suites dials `127.0.0.1`. Those are not the same port. An unrelated
process already holding the IPv4 wildcard on the number the kernel hands
out keeps receiving the loopback traffic, so the probe is answered by that
process and the test's own server never sees a connection. Confirmed by
`lsof` at the moment of failure, which showed a foreign IPv4 listener and
the test's IPv6 listener on one port, and reproduced deliberately with a
stand-in process: an unspecified bind hands the reply to the stranger, a
loopback bind reaches the intended app.

Pin the bind address in the shared transport harness and in the seven
sibling suites that bound the same way, and add a harness self-test on the
address so dropping it fails here rather than silently reappearing as a
flake somewhere else. A specific bind takes precedence over a wildcard
holder, so a probe now reaches its own app or nothing at all.

No behaviour under test changes: no assertion is weakened, no retry or
timeout is added, and no runtime string is touched.

Verified: a stress rig that failed three times in 2000 cycles now runs
6000 clean; 35 and then 32 consecutive green runs of the CORS suite under
ten busy cores; the full package green at 1612 passing; typecheck and
Prettier clean.
@ranst91
ranst91 requested a review from a team as a code owner September 3, 2026 12:33
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Python Preview Packages

Version 0.0.0.dev1788438802 published to TestPyPI.

Warning: These packages are built from contributor code that may not yet have been vetted for correctness or security. Install at your own risk and do not use in production.

Install with uv

Add the TestPyPI index to your pyproject.toml:

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = true

Then install the packages you need:

# Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1788438802' --index testpypi

# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1788438802' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1788438802' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1788438802' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1788438802' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1788438802' --index testpypi

Install with pip

pip install \
  --index-url https://test.pypi.org/simple/ \
  --extra-index-url https://pypi.org/simple/ \
  ag-ui-protocol==0.0.0.dev1788438802

Use --extra-index-url https://pypi.org/simple/ so pip can resolve
transitive dependencies (pydantic, fastapi, etc.) from real PyPI.


Commit: 81cd60d

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@ag-ui/a2a-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a-middleware@2621

@ag-ui/a2ui-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-middleware@2621

@ag-ui/event-throttle-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/event-throttle-middleware@2621

@ag-ui/mcp-apps-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-apps-middleware@2621

@ag-ui/mcp-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-middleware@2621

@ag-ui/a2a

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a@2621

@ag-ui/adk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/adk@2621

@ag-ui/ag2

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/ag2@2621

@ag-ui/agno

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/agno@2621

@ag-ui/aws-strands

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/aws-strands@2621

@ag-ui/claude-agent-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-agent-sdk@2621

@ag-ui/claude-managed-agents

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-managed-agents@2621

@ag-ui/crewai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/crewai@2621

@ag-ui/langchain

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langchain@2621

@ag-ui/langgraph

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langgraph@2621

@ag-ui/llamaindex

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/llamaindex@2621

@ag-ui/mastra

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mastra@2621

@ag-ui/pydantic-ai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/pydantic-ai@2621

@ag-ui/vercel-ai-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/vercel-ai-sdk@2621

@ag-ui/watsonx

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/watsonx@2621

@ag-ui/a2ui-toolkit

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-toolkit@2621

create-ag-ui-app

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/create-ag-ui-app@2621

@ag-ui/client

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/client@2621

@ag-ui/core

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/core@2621

@ag-ui/encoder

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/encoder@2621

@ag-ui/proto

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/proto@2621

commit: 98fc36e

@AlemTuzlak
AlemTuzlak merged commit ff41588 into main Sep 3, 2026
41 of 42 checks passed
@AlemTuzlak
AlemTuzlak deleted the claude/distracted-goodall-68fa01 branch September 3, 2026 13:46
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.

2 participants