Pre-flight Checklist
Problem or Motivation
The AWS Strands adapter does not surface citation data to the front end. When a Bedrock (e.g. Claude) model returns citations, the adapter receives the citation event from the Strands stream but has no branch for it, so the citation data is dropped and the user sees an answer with no sources.
The AG-UI core protocol has no citation type, and this request deliberately does not try to add one. Instead, it keeps the change inside the Strands adapter and carries the citation through the existing CUSTOM event. (The broader silent-drop of unmapped events is tracked separately as a bug in #2291 ; this request adds one purpose-built citation handler.)
Proposed Solution
Add a branch to the Strands adapter event loop, alongside the existing text and reasoning branches, that catches the citation event and emits a CUSTOM event under a stable name such as "citation". Give that event a structured value rather than a flattened string:
The front end can then subscribe to the CUSTOM event by name and render the citation. The same branch should be added to both the Python and the TypeScript adapters. This approach follows a pattern the adapter already uses: it emits CUSTOM events for other named concepts, such as the multi-agent handoff (agent.py:1174).
Alternatives Considered
- Add a first-class citation type to the core protocol. This would give normalized citations across every integration, but it is a much larger change that touches the core packages, the proto, and the client, and it needs protocol-level agreement. This request intentionally avoids that scope.
- Keep the current behavior. This loses the citation data outright, so it is not acceptable.
- Forward a
RAW event instead. A RAW event preserves the raw Strands shape but forces every front end to parse that shape itself. A CUSTOM event with a stable, documented value is cleaner to consume. (The general RAW fallback is Ticket A, and is complementary rather than a substitute.)
Additional Context
I read the Strands SDK source to confirm that the citation data is available at the adapter boundary. I have had to patch this adapter on my own system which means I need to manually merge in any upstream changes to the core package which has been working and I see value in providing the citations feature to other users of the protocol for Strands.
Python (strands-agents), strands/event_loop/streaming.py:
elif "citation" in delta_content:
state["citationsContent"].append(delta_content["citation"])
typed_event = CitationStreamEvent(delta=delta_content, citation=delta_content["citation"])
The citation reaches stream_async as a top-level event["citation"] key, in the same way text arrives as event["data"] and reasoning as event["reasoningText"]. The payload (CitationsDelta) carries the optional fields location, sourceContent (a list of {text}), and title, where location is one of documentChar, documentPage, documentChunk, searchResultLocation, or web.
Version note: the adapter pins strands-agents >= 1.15.0. CitationStreamEvent has existed since v1.15.0, but its dict shape changed within the supported range:
| Version |
Shape |
| v1.15.0 to v1.20.0 |
nested — {"callback": {"citation", "delta"}} |
| v1.30.0 and later |
top-level — {"citation", "delta"} |
The branch should handle both shapes, or read the stable citationsContent block that the SDK assembles at block-stop, or the team should raise the version floor.
TypeScript (@strands-agents/sdk), strands-ts/src/models/streaming.ts:
export type ContentBlockDelta = TextDelta | ToolUseInputDelta | ReasoningContentDelta | CitationsDelta
export interface CitationsDelta {
type: 'citationsDelta'
citations: Citation[]
content: CitationGeneratedContent[] // [{ text }]
}
Here the branch condition is delta.type === "citationsDelta".
Files to change:
integrations/aws-strands/python/src/ag_ui_strands/agent.py - add the citation branch.
integrations/aws-strands/typescript/src/agent.ts - add the citationsDelta branch.
- The integration README - document the new
CUSTOM event name and its value.
Pre-flight Checklist
Problem or Motivation
The AWS Strands adapter does not surface citation data to the front end. When a Bedrock (e.g. Claude) model returns citations, the adapter receives the citation event from the Strands stream but has no branch for it, so the citation data is dropped and the user sees an answer with no sources.
The AG-UI core protocol has no citation type, and this request deliberately does not try to add one. Instead, it keeps the change inside the Strands adapter and carries the citation through the existing
CUSTOMevent. (The broader silent-drop of unmapped events is tracked separately as a bug in #2291 ; this request adds one purpose-built citation handler.)Proposed Solution
Add a branch to the Strands adapter event loop, alongside the existing text and reasoning branches, that catches the citation event and emits a
CUSTOMevent under a stable name such as"citation". Give that event a structured value rather than a flattened string:{ "type": "CUSTOM", "name": "citation", "value": { "messageId": "…", // links the citation to the assistant message "sourceId": "…", "title": "…", "url": "…", "location": { /* documentIndex/start/end, searchResultIndex, or web */ }, "citedText": "…", "provider": "bedrock", "metadata": { /* extra provider fields that do not fit above */ } } }The front end can then subscribe to the
CUSTOMevent by name and render the citation. The same branch should be added to both the Python and the TypeScript adapters. This approach follows a pattern the adapter already uses: it emitsCUSTOMevents for other named concepts, such as the multi-agent handoff (agent.py:1174).Alternatives Considered
RAWevent instead. ARAWevent preserves the raw Strands shape but forces every front end to parse that shape itself. ACUSTOMevent with a stable, documented value is cleaner to consume. (The generalRAWfallback is Ticket A, and is complementary rather than a substitute.)Additional Context
I read the Strands SDK source to confirm that the citation data is available at the adapter boundary. I have had to patch this adapter on my own system which means I need to manually merge in any upstream changes to the core package which has been working and I see value in providing the citations feature to other users of the protocol for Strands.
Python (
strands-agents),strands/event_loop/streaming.py:The citation reaches
stream_asyncas a top-levelevent["citation"]key, in the same way text arrives asevent["data"]and reasoning asevent["reasoningText"]. The payload (CitationsDelta) carries the optional fieldslocation,sourceContent(a list of{text}), andtitle, wherelocationis one ofdocumentChar,documentPage,documentChunk,searchResultLocation, orweb.Version note: the adapter pins
strands-agents >= 1.15.0.CitationStreamEventhas existed since v1.15.0, but its dict shape changed within the supported range:{"callback": {"citation", "delta"}}{"citation", "delta"}The branch should handle both shapes, or read the stable
citationsContentblock that the SDK assembles at block-stop, or the team should raise the version floor.TypeScript (
@strands-agents/sdk),strands-ts/src/models/streaming.ts:Here the branch condition is
delta.type === "citationsDelta".Files to change:
integrations/aws-strands/python/src/ag_ui_strands/agent.py- add the citation branch.integrations/aws-strands/typescript/src/agent.ts- add thecitationsDeltabranch.CUSTOMevent name and its value.