Skip to content

docs(aws-strands): cut the documentation to LangGraph's shape, and test what is left - #2620

Closed
ranst91 wants to merge 2 commits into
mainfrom
claude/sad-jones-f33548
Closed

docs(aws-strands): cut the documentation to LangGraph's shape, and test what is left#2620
ranst91 wants to merge 2 commits into
mainfrom
claude/sad-jones-f33548

Conversation

@ranst91

@ranst91 ranst91 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Cuts this integration's documentation from 2,590 lines to 765, deletes
ARCHITECTURE.md, and adds tests that read what is left so it cannot drift back.

Why

A truth pass on these four documents corrected roughly fifty false claims. The
classes recurred: counted quantities stated in prose, quoted signatures,
example-table claims about which hooks a demo uses, and claims about what the
package exports.

Two things follow from that, and this PR does both.

The first is that the volume was the problem. LangGraph, the reference shape,
documents the same kind of bridge in 486 lines. This integration had 2,590, and
the extra 2,100 were essays nobody read and nothing checked. The dojo is the
real support surface: spin it up and whatever demo it has is supported. These
documents should be a cheap stand-in for a docs site, not the docs site.

The second is that whatever survives needs a reader. The one claim class that
never drifted was the one the repository already had a test for.

The cut

Before After
ARCHITECTURE.md 382 deleted
python/README.md 764 194
python/examples/README.md 146 174
typescript/README.md 1,298 277
typescript/examples/README.md absent 120
Total 2,590 765

The document set now matches LangGraph's exactly. That includes adding a
TypeScript examples README, which LangGraph ships and this integration did not,
so its fifteen TypeScript demos were documented only inside the package README.

Deleted: the AgentCore narration, the citations essays, the per-provider
stop-reason surveys, the multi-agent and thread-guard prose, the RAW passthrough
sections, the URL-fetch and invocation-state sections, the restated error-code
tables, and about 300 lines of cross-origin narrative. Where a reader might want
an explanation, the document links the demo instead.

Three regions moved out of ARCHITECTURE.md before it went, because tests read
them: the 32-name packaging surface and the two quoted Python signatures into
python/README.md, and the fifteen-row example table into
python/examples/README.md.

The levers

Six, each in the existing test file for its subject. Every value is derived,
from the document by parsing a structured region of it and from the source by
enumerating it. No lever carries an expected count or name list beside the
test, because that is the same drift relocated into a file where it is less
visible than in prose.

  • Route tables against the DEMOS registry, by set and by length, so a
    duplicated row cannot hide inside the set comparison.
  • Numerals against derived sets: the example files that carry a standalone
    runner, and the package.json scripts that point at one, the scripted set
    derived by relationship rather than by counting. Plus the named complement, so
    the sentence and the numeral cannot disagree.
  • Named imports in every ts fence against the real entry namespaces, with
    type-only imports excluded since they are not runtime keys.
  • The install fence against this package's non-optional peers and the
    installed Strands SDK's own, read off its package.json, with both fence
    numerals derived from those manifests.
  • The packaging surface against __all__ three ways: the name set, the block
    size, and the prose numeral, so editing the sentence alone cannot satisfy it
    and neither can editing the block alone.
  • Quoted signatures against inspect.signature, as ordered sequences, with
    the surface taken from __all__.
  • Example-table identifiers against the primitives each demo actually calls,
    by AST walk, set-equal so both directions are covered.

What the cut is bounded by

Five test files read these documents, which is what decided where the cut
stopped. Kept verbatim: the three route tables, the install fence, the Quick
Start and Key Files numerals, the corsOrigin table that the CORS fixtures
parse in both directions, and the resume shapes, reserved name prefix and
approval-metadata passage the docs-contract suites anchor on.

The TypeScript README landed at 277 rather than the 220 first targeted. The
regions that had to survive verbatim already total about 240, so going lower
would have meant cutting into a tested region.

Two things this found

  • Two example-table rows were wrong, both by omission, which is the
    direction a one-way check misses. predictive_state_updates.py named only
    PredictStateMapping where the demo also uses state_from_args and
    state_context_builder; a2ui_recovery.py named nothing where it sets
    StrandsAgentConfig.a2ui. Both corrected, in the words the demos' own
    docstrings use.
  • The new examples README reintroduced the problem. It repeated counts that
    were checked only in the package README, which is exactly the class this
    branch exists to close. The numeral lever now reads both documents, and also
    holds the project tree to what is on disk in both directions, which is the
    direction LangGraph's own tree is stale in today.

Two design notes

Both are places where the corrected text falsified the simpler rule.

  • The example-table vocabulary. Taking it as every dataclass field plus every
    config class name drags in StrandsAgent, StrandsAgentConfig, ToolBehavior
    and tool_behaviors, which every configured demo constructs and no row names,
    and fails all fifteen rows. It is now one concept per dataclass field, aliased
    to the exported type named in that field's annotation, with the container field
    skipped because its annotation names ToolBehavior. Both exclusions are
    derived, and a guard test fails if the derivation ever yields nothing, since an
    empty vocabulary would report fifteen agreements about nothing.
  • Telling a documented signature from an example call. "The code span starts
    the line" is not enough: a README sentence legitimately opens with
    `ToolBehavior(continue_after_frontend_call=False)`, which passes a chosen
    value where the signature names a parameter. A signature is now a span that
    opens a list item, and the set of callables the scan finds is pinned so a
    signature cannot quietly vanish from the prose instead of failing.

Every assertion is scoped to a structured region: a table row, a fence, an
import statement, a signature span, an anchored sentence. Nothing does an
unscoped substring search over a whole document, and every anchor fails loudly
if the phrase it keys on is reworded rather than silently ceasing to assert.

Deliberately not built

  • The TypeScript counterpart of the signature lever. addStrandsExpressEndpoint's
    option list needs an AST read of endpoint.ts.
  • The quoted-sentence substring check. It cannot see a truncated quote, since a
    truncation is still a substring, and it goes red on a legitimate paraphrase.
  • Any documentation assertion on error-codes.json or its two table helpers.
    That file's own about block records why: it is data, not a reading of either
    source. Its helper weaknesses are a separate hardening task.
  • Anything covering self-contradiction between two pieces of prose, behavioural
    and causal claims, or the English-descriptor half of an example-table row.
    Those have no in-repo falsifier.

Verification

Every lever was driven red before green: the document, or for the derived side
the source, was broken in the way the class actually drifted, the failure was
confirmed to name the problem, the file was restored, and the test confirmed
green. That includes the cases a weaker test would pass: a duplicated route row
that is set-equal but the wrong length, a stripped runner where the numeral
stays correct and only the complement set changes, a prose numeral edited to
match a shortened block, a parameter reorder that a set comparison accepts, an
example-table row wrong by omission, and a project-tree directory that is right
about what it names but silent about what was added.

Each relocated region was driven red again in its new home after the move.

uv run pytest in integrations/aws-strands/python: 1,289 passed.
pnpm exec vitest run in integrations/aws-strands/typescript: 1,620 passed.
The examples package: 96 passed.

Not changed

No runtime string, error code or message text. error-codes.json still carries
the same 26 codes; its only edit is one prose sentence in the about block that
pointed at the deleted file.

Every reference to ARCHITECTURE.md was repointed or removed across
error-codes.json, src/agent.ts and five test files, keeping the sentence
wherever it still asserted something true. The agent.ts change is
comment-only. A repo-wide sweep confirms no dangling reference remains.

One thing did leave the repository: the Python-versus-TypeScript hook-reporting
divergence, nine reported sites on one side and eight on the other, now lives
only in code docstrings rather than in any document.

Unrelated, pre-existing

src/__tests__/cors.test.ts fails roughly one run in six under load, in a test
that binds a real port. Untouched by this branch.

@ranst91
ranst91 requested a review from a team as a code owner September 3, 2026 08:28
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Python Preview Packages

Version 0.0.0.dev1788434090 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.dev1788434090' --index testpypi

# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1788434090' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1788434090' --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.dev1788434090' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1788434090' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1788434090' --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.dev1788434090

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


Commit: a06d9e5

@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@2620

@ag-ui/a2ui-middleware

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

@ag-ui/event-throttle-middleware

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

@ag-ui/mcp-apps-middleware

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

@ag-ui/mcp-middleware

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

@ag-ui/a2a

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

@ag-ui/adk

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

@ag-ui/ag2

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

@ag-ui/agno

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

@ag-ui/aws-strands

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

@ag-ui/claude-agent-sdk

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

@ag-ui/claude-managed-agents

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

@ag-ui/crewai

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

@ag-ui/langchain

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

@ag-ui/langgraph

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

@ag-ui/llamaindex

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

@ag-ui/mastra

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

@ag-ui/pydantic-ai

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

@ag-ui/vercel-ai-sdk

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

@ag-ui/watsonx

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

@ag-ui/a2ui-toolkit

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

create-ag-ui-app

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

@ag-ui/client

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

@ag-ui/core

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

@ag-ui/encoder

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

@ag-ui/proto

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

commit: 352049b

@ranst91
ranst91 force-pushed the claude/sad-jones-f33548 branch from 5bfcf8e to 6f3fb19 Compare September 3, 2026 11:14
@ranst91 ranst91 changed the title test(aws-strands): read the documents that keep drifting docs(aws-strands): cut the documentation to LangGraph's shape, and test what is left Sep 3, 2026
The truth pass on the four Strands documents corrected roughly fifty false
claims, in four recurring classes: counted quantities stated in prose, quoted
signatures, example-table claims about which hooks a demo uses, and claims
about what a package exports. The one class that did not drift is the one
class the repository already had a lever for.

Six levers, each in the existing test file for its subject. Every value is
derived, from the document by parsing a structured region of it and from the
source by enumerating it, so none of them carries an expected count or name
list beside the test.

- The TypeScript README route table against the DEMOS registry, by set and by
  length, mirroring the Python route-table test that held.
- The README's runner and script numerals against the files that carry a
  standalone runner and the package.json scripts that point at one, plus the
  named complement so the sentence and the numeral cannot disagree.
- Named imports in every ts fence against the real entry namespaces, and the
  install fence against this package's non-optional peers and the installed
  Strands SDK's own, with both fence numerals derived from those manifests.
- The ARCHITECTURE packaging-surface block against __all__ three ways: the
  name set, the block size and the prose numeral, so editing the sentence
  alone cannot satisfy it.
- Every signature the documents quote against inspect.signature, as ordered
  sequences, with the surface taken from __all__.
- Each example-table row's identifiers against the primitives the demo
  actually uses, by AST walk, set-equal so both directions are covered.

The example-table lever found two rows wrong by omission, which is the
direction a one-way check misses, and both are corrected here:
predictive_state_updates.py also uses state_from_args and
state_context_builder, and a2ui_recovery.py sets StrandsAgentConfig.a2ui.

Every lever was driven red before green, including the cases a weaker test
would pass: a duplicated row that is set-equal but the wrong length, a
stripped runner whose numeral stays correct, a prose numeral edited to match
a shortened block, and a parameter reorder a set comparison accepts.
This integration carried 2,590 lines of documentation across four documents.
LangGraph, the reference shape, carries 486. The dojo is the real support
surface: spin it up and whatever demo it has is supported, so these documents
should be a cheap stand-in for a docs site rather than the docs site itself.

2,590 lines to 765, and the document set now matches LangGraph's exactly.

- ARCHITECTURE.md deleted, 382 lines.
- python/README.md 764 to 194.
- typescript/README.md 1,298 to 277.
- python/examples/README.md 146 to 174, gaining the example table.
- typescript/examples/README.md added, 120 lines. LangGraph ships one and this
  integration had none, so its fifteen TypeScript demos were documented only
  inside the package README.

Gone: the AgentCore narration, the citations essays, the per-provider
stop-reason surveys, the multi-agent and thread-guard prose, the RAW passthrough
sections, the URL-fetch and invocation-state sections, the restated error-code
tables, and roughly 300 lines of cross-origin narrative. Where a reader might
want an explanation, the document links the demo instead.

Three regions moved out of ARCHITECTURE.md before it went, because tests read
them: the 32-name packaging surface and the two quoted Python signatures into
python/README.md, and the fifteen-row example table into
python/examples/README.md. All six documentation levers survive, repointed, and
each relocated region was driven red in its new home before green.

The cut is bounded by what the suites read. Kept verbatim: the three route
tables, the install fence and its two numerals, the Quick Start and Key Files
numerals, the corsOrigin table that the CORS fixtures parse in both directions,
and the resume shapes, reserved prefix and approval-metadata passage the
docs-contract suites anchor on.

The new examples README repeated counts that were checked only in the package
README, which would have reintroduced the class this branch exists to close, so
the numeral lever now reads both documents and also holds the project tree to
what is on disk in both directions.

Every reference to the deleted file was repointed or removed across
error-codes.json, agent.ts and five test files, with the sentence kept wherever
it still asserted something true. No runtime string, error code or message text
changed; error-codes.json still carries the same 26 codes.
@ranst91
ranst91 force-pushed the claude/sad-jones-f33548 branch from 352049b to 2541908 Compare September 3, 2026 13:28
@ranst91 ranst91 closed this Sep 3, 2026
@ranst91
ranst91 deleted the claude/sad-jones-f33548 branch September 3, 2026 13:28
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