Summary
Add a MessageCollectionAttachment that represents multiple heterogeneous attachments as one logical, durable attachment.
This addresses cases where clients present one attachment but the model needs several pieces of context:
- Browser element: structured text plus an inline screenshot.
- Directory: directory resource plus eagerly attached images.
- Future compound resources such as document bundles.
Today these pieces must be flattened into Message.attachments. After replay, clients cannot reliably reconstruct the original logical grouping and render every piece independently.
Proposed shape
export const enum MessageAttachmentKind {
Simple = 'simple',
EmbeddedResource = 'embeddedResource',
Resource = 'resource',
Annotations = 'annotations',
Chat = 'chat',
Collection = 'collection',
}
export type MessageCollectionItem =
| SimpleMessageAttachment
| MessageEmbeddedResourceAttachment
| MessageResourceAttachment
| MessageAnnotationsAttachment
| MessageChatAttachment;
/**
* Multiple attachments presented by the originating client as one logical item.
*
* The collection has no model representation of its own. Hosts flatten its
* attachments when constructing model context, while preserving the collection
* in durable message state for replay.
*/
export interface MessageCollectionAttachment extends MessageAttachmentBase {
type: MessageAttachmentKind.Collection;
/**
* Ordered attachments composing this logical item.
*
* Collections cannot contain other collections.
* This array MUST contain at least one attachment.
*/
attachments: MessageCollectionItem[];
}
export type MessageAttachment =
| SimpleMessageAttachment
| MessageEmbeddedResourceAttachment
| MessageResourceAttachment
| MessageAnnotationsAttachment
| MessageChatAttachment
| MessageCollectionAttachment;
Semantics
Durable state and presentation
- The collection is stored in
Message.attachments as a single item.
- Clients SHOULD render it as one logical attachment using the collection’s
label, displayKind, and _meta.
- Clients MAY expose its constituent attachments in expanded or detailed UI.
- Clients MUST NOT render its members as independent top-level attachments.
Model context
The collection itself has no model representation.
When accepting a message, hosts MUST process each member in order exactly as if it appeared directly in Message.attachments. This is a one-level flattening operation; collection attachments cannot nest.
This keeps AHP focused on durable presentation state while leaving provider-specific model translation to the host.
Ordering and ranges
- Member order is significant and MUST be preserved.
- Producers SHOULD place the message-text
range on the collection.
- A member’s range, when present, continues to describe that member.
Metadata
Collection and member metadata are independent:
- Collection
_meta describes the logical item.
- Member
_meta describes that particular model-facing attachment.
- Hosts MUST preserve both without merging them.
Examples
Browser element
{
"type": "collection",
"label": "button#submit",
"displayKind": "element",
"attachments": [
{
"type": "simple",
"label": "button#submit structure",
"modelRepresentation": "Element: button#submit\n\n..."
},
{
"type": "embeddedResource",
"label": "button#submit screenshot",
"displayKind": "image",
"contentType": "image/jpeg",
"data": "..."
}
]
}
Directory with resolved images
{
"type": "collection",
"label": "design-assets",
"displayKind": "directory",
"attachments": [
{
"type": "resource",
"label": "design-assets",
"displayKind": "directory",
"uri": "file:///workspace/design-assets"
},
{
"type": "resource",
"label": "hero.png",
"displayKind": "image",
"uri": "file:///workspace/design-assets/hero.png"
}
]
}
Why collections are not recursive
A restricted member union makes cycles and unbounded nesting impossible by construction.
This follows the existing ContainerCustomizationBase / ChildCustomization pattern, where container customization kinds are excluded from the child union. It also avoids requiring runtime recursion rules like those needed for chat attachments.
Compatibility
An unknown collection variant cannot be ignored coherently because doing so also discards all contained model context. Therefore this should not be treated like an optional rendering-only variant.
Recommended rollout:
- Introduce it in a new negotiated protocol version.
- Hosts speaking an older version flatten collections into ordinary top-level attachments.
- Hosts speaking the new version preserve collections in durable state.
- If rollout across mixed-version clients requires finer gating, add an
attachmentCollections client capability and flatten for clients that do not advertise it.
This preserves today’s degraded behavior—independent attachments—for older clients rather than losing the attachments entirely.
Alternatives considered
Correlation through _meta
Attach a shared UUID to otherwise independent attachments.
This works as an implementation-specific bridge, but clients must understand private metadata and grouping remains best-effort. Once grouping is required for interoperable replay, AHP doctrine recommends graduating it into typed state.
Group fields on flat attachments
Add a group identifier and repeated group metadata to each attachment.
This gives excellent old-client degradation, but loses atomicity, duplicates metadata, and requires clients to reconcile incomplete or inconsistent groups.
Add binary content to SimpleMessageAttachment
This covers text-plus-image but not general one-to-many cases such as directories or document bundles.
Implementation impact
Expected changes in microsoft/agent-host-protocol:
- Add the kind, interfaces, and union membership in
types/channels-chat/state.ts.
- Document collection acceptance and replay semantics in
docs/specification/chat-channel.md.
- Add a changelog fragment under
docs/.changes/.
- Regenerate schemas and TypeScript, Rust, Kotlin, Swift, and Go clients.
- Add schema/generator coverage.
- No reducer changes should be required because existing message-bearing actions already preserve
Message.attachments.
Relevant precedent
Summary
Add a
MessageCollectionAttachmentthat represents multiple heterogeneous attachments as one logical, durable attachment.This addresses cases where clients present one attachment but the model needs several pieces of context:
Today these pieces must be flattened into
Message.attachments. After replay, clients cannot reliably reconstruct the original logical grouping and render every piece independently.Proposed shape
Semantics
Durable state and presentation
Message.attachmentsas a single item.label,displayKind, and_meta.Model context
The collection itself has no model representation.
When accepting a message, hosts MUST process each member in order exactly as if it appeared directly in
Message.attachments. This is a one-level flattening operation; collection attachments cannot nest.This keeps AHP focused on durable presentation state while leaving provider-specific model translation to the host.
Ordering and ranges
rangeon the collection.Metadata
Collection and member metadata are independent:
_metadescribes the logical item._metadescribes that particular model-facing attachment.Examples
Browser element
{ "type": "collection", "label": "button#submit", "displayKind": "element", "attachments": [ { "type": "simple", "label": "button#submit structure", "modelRepresentation": "Element: button#submit\n\n..." }, { "type": "embeddedResource", "label": "button#submit screenshot", "displayKind": "image", "contentType": "image/jpeg", "data": "..." } ] }Directory with resolved images
{ "type": "collection", "label": "design-assets", "displayKind": "directory", "attachments": [ { "type": "resource", "label": "design-assets", "displayKind": "directory", "uri": "file:///workspace/design-assets" }, { "type": "resource", "label": "hero.png", "displayKind": "image", "uri": "file:///workspace/design-assets/hero.png" } ] }Why collections are not recursive
A restricted member union makes cycles and unbounded nesting impossible by construction.
This follows the existing
ContainerCustomizationBase/ChildCustomizationpattern, where container customization kinds are excluded from the child union. It also avoids requiring runtime recursion rules like those needed for chat attachments.Compatibility
An unknown collection variant cannot be ignored coherently because doing so also discards all contained model context. Therefore this should not be treated like an optional rendering-only variant.
Recommended rollout:
attachmentCollectionsclient capability and flatten for clients that do not advertise it.This preserves today’s degraded behavior—independent attachments—for older clients rather than losing the attachments entirely.
Alternatives considered
Correlation through
_metaAttach a shared UUID to otherwise independent attachments.
This works as an implementation-specific bridge, but clients must understand private metadata and grouping remains best-effort. Once grouping is required for interoperable replay, AHP doctrine recommends graduating it into typed state.
Group fields on flat attachments
Add a group identifier and repeated group metadata to each attachment.
This gives excellent old-client degradation, but loses atomicity, duplicates metadata, and requires clients to reconcile incomplete or inconsistent groups.
Add binary content to
SimpleMessageAttachmentThis covers text-plus-image but not general one-to-many cases such as directories or document bundles.
Implementation impact
Expected changes in
microsoft/agent-host-protocol:types/channels-chat/state.ts.docs/specification/chat-channel.md.docs/.changes/.Message.attachments.Relevant precedent