microsoft / microsoft/agent-host-protocol

Proposal: ChatSummary message preview for catalog rendering without subscribing

Open
#273 1 comment 1 reaction 1 assignee View on GitHub

@connor4312 is already working on this.

Since Jun 26, 2026.

Dominant language
TypeScript
Stars
348
Forks
122
Avg merge
14h 12m
Merged PRs (30d)
22

Description

Summary

Add an optional, short, server-truncated last-message preview to the catalog representation of a chat (ChatSummary) so a client can render a conversation list — the newest line of each thread — without subscribing to every chat channel. This mirrors the existing precedent of ChangesSummary (#191) and the session-level inputNeeded aggregate (#265): surface a cheap rollup on the catalog so constrained clients avoid the heavy per-chat subscription.

Motivation

A session with many chats (sub-agent fan-out, parallel threads, an agent team) renders in a UI as a list, each row showing the thread's latest activity. Today ChatSummary carries title, status, activity?, and modifiedAt — but no content peek. To show "…the last thing said in this thread," a client must subscribe to the chat and pull its ChatState (the full turn history). For a list of N chats that is N subscriptions and N histories to render N preview lines.

The catalog is meant to be the cheap layer that lets a client decide what to drill into; a preview keeps it cheap. activity does not fill this role: it is the in-progress status verb ("Editing files…"), not message content, and it is absent when the chat is idle — which is exactly when a "last message" preview is most useful.

Why this belongs in AHP (not a per-host _meta convention)

The catalog/summary split is already an AHP concept, and AHP already places derived rollups on summaries for precisely this reason:

  • ChangesSummary on SessionSummary"a quick at-a-glance view of the session's footprint… without requiring the client to subscribe to a changeset."
  • AnnotationsSummary on SessionSummary — counts surfaced "so badge UI can render… without subscribing."
  • SessionState.inputNeeded (#265) — outstanding input surfaced on the session channel so a client can act "without subscribing to each chat."

A last-message preview is the same shape of thing and should be modeled the same, native way — not as a per-host metadata convention that every client has to special-case to render a basic chat list.

Proposed shape (illustrative — open to bikeshedding)

export interface ChatSummary {
  // ...existing fields...
  /**
   * Optional short preview of the most recent message/response in the chat,
   * for list rendering. Server-truncated; clients MUST treat it as lossy and
   * MUST NOT parse it for structure. Absent ⇒ no preview available (e.g. an
   * empty chat, or a host that chooses not to surface content into the catalog).
   */
  preview?: MessagePreview;
}

export interface MessagePreview {
  /** Who produced the previewed content. Reuses the MessageKind vocabulary. */
  role: MessageKind; // 'user' | 'agent' | 'tool' | 'systemNotification'
  /** Plain-text, server-truncated snippet (no markdown-structure guarantee). */
  text: string;
  /** Optional timestamp of the previewed message/response (ISO-8601). */
  at?: string;
}
  • Optional and additive — old peers ignore it.
  • Small by contract — it rides in session/chat lists and in root/sessionSummaryChanged-style notifications, the same place the existing "producers SHOULD keep the payload small" guidance already applies to SessionSummary._meta.
  • Reuses MessageKind rather than inventing a fresh role enum.
  • Privacy-aware — a preview lifts conversation content into the catalog/list layer. A host that treats the catalog as lower-trust than the chat channel MAY omit it; absence is always valid.

Relationship to existing / in-flight work

  • #187 / #264 restructure where SessionSummary lives and its timestamp representation; this is an additive field on the chat catalog entry and is orthogonal — it should slot into whichever ChatSummary shape #264 settles on.
  • #191 (ChangesSummary) and #265 (inputNeeded) are the direct precedents this follows.
  • Pairs naturally with the bounded-snapshot proposal (subscribe view): windowing makes subscribing to a chat cheap; preview makes not subscribing — just listing — cheap.

Open questions

  • Bubble to SessionSummary? Should a session's most-recently-active chat preview also surface on SessionSummary so a session list (not just a chat list within one session) can show a line? Likely yes, sourced from the session's default/most-recent chat.
  • Part kind. Include a tiny discriminator (text vs tool-result vs reasoning) so a UI can render 🔧 ran tests vs a text snippet, or keep it pure text for v1?
  • Length contract. Leave truncation length entirely to the host (recommended), or suggest a soft cap so list rows are visually consistent across hosts?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.