MessagePart (src/Messages/DTO/MessagePart.php) can carry exactly seven things:
channel, type, thoughtSignature, text, file, functionCall,
functionResponse. None of them can hold a citation.
All three first-party providers return source attribution, in three different
shapes (per vendor documentation):
| Provider |
Field |
| Anthropic |
citations on text blocks — cited_text, document_index, document_title, typed location |
| OpenAI |
annotations — type: "url_citation", url, title, start_index, end_index, plus sources |
| Gemini |
citationMetadata.citationSources and groundingMetadata; annotations/url_citation on the Search-grounding surface |
And all three provider packages currently drop it. Verified by reading the source:
AnthropicTextGenerationModel::parseResponseContentMessagePart()'s case 'text'
keeps only $partData['text']; GoogleTextGenerationModel and
OpenAiTextGenerationModel contain no citation/grounding/annotation handling at all.
This is a gap rather than a data-loss bug — no provider currently requests
citations, so nothing is being lost in production today. But the parse paths are
not ready, and no provider can be made ready while the DTO has nowhere to put the
result.
Suggested shape: thoughtSignature is the precedent — an opaque,
provider-supplied, round-trippable field already accepted on MessagePart. A
citation carrier could follow it, normalising the three vendor shapes into one
representation (source identifier/URI and optional title).
Related: #268 (provider-agnostic text extraction) — same theme of getting
structured meaning out of documents.
Happy to open a PR once maintainers settle the shape; the API-surface decision is
yours.
MessagePart(src/Messages/DTO/MessagePart.php) can carry exactly seven things:channel,type,thoughtSignature,text,file,functionCall,functionResponse. None of them can hold a citation.All three first-party providers return source attribution, in three different
shapes (per vendor documentation):
citationson text blocks —cited_text,document_index,document_title, typed locationannotations—type: "url_citation",url,title,start_index,end_index, plussourcescitationMetadata.citationSourcesandgroundingMetadata;annotations/url_citationon the Search-grounding surfaceAnd all three provider packages currently drop it. Verified by reading the source:
AnthropicTextGenerationModel::parseResponseContentMessagePart()'scase 'text'keeps only
$partData['text'];GoogleTextGenerationModelandOpenAiTextGenerationModelcontain no citation/grounding/annotation handling at all.This is a gap rather than a data-loss bug — no provider currently requests
citations, so nothing is being lost in production today. But the parse paths are
not ready, and no provider can be made ready while the DTO has nowhere to put the
result.
Suggested shape:
thoughtSignatureis the precedent — an opaque,provider-supplied, round-trippable field already accepted on
MessagePart. Acitation carrier could follow it, normalising the three vendor shapes into one
representation (source identifier/URI and optional title).
Related: #268 (provider-agnostic text extraction) — same theme of getting
structured meaning out of documents.
Happy to open a PR once maintainers settle the shape; the API-surface decision is
yours.