Skip to content

ListTasks returns a task's messages and artifacts as two unordered lists, so a transcript cannot be replayed in order #2584

Description

@Charlesthebird

What happens

In a conversation where the agent asks the reader something with ask_user, the
transcript renders out of order: every message the reader sent appears above every
message the agent sent, so the answers sit above the questions they answer.

Read back from a real cluster, ListTasks returns this for one such task:

TASK 01a03efd-bfea   state=COMPLETED   history=3   artifacts=7
  history[0]   user    "ask me a question"
  history[1]   user    "Personal development"      <- 1st answer
  history[2]   user    "none"                      <- 2nd answer
  artifact[0]  agent   ask_user called
  artifact[1]  agent   ask_user result (pending)
  artifact[2]  agent   ask_user result (answered)
  artifact[3]  agent   ask_user called
  artifact[4]  agent   ask_user result (pending)
  artifact[5]  agent   ask_user result (answered)
  artifact[6]  agent   "Thank you for sharing..."

Every message the reader sent is in history; every message the agent produced is in
artifacts. They are two parallel lists, and nothing in the response says how to
interleave them.

Why a client cannot fix it properly

  • Timestamps do not separate them. Every message in a task carries the task's
    single status.timestamp, so a client sorting by time gets one bucket.
  • Only one side is time-ordered by id. Artifact ids are UUIDv7 and sort correctly
    (01a03efd-c565 ... 01a03efe-0482). Message ids in history are minted by the
    client that sent them and are UUIDv4, carrying no time.
  • The correlation ids do not match across the two lists. An answer in history
    carries {"type":"ask_user_response","id":"adk-c9f53704-..."} in its metadata under
    https://kagent.dev/extensions/hitl/v1. The ask_user call it answers carries the
    model's own id, call_kEdJ3FU3x0W6rHytuDznM732. Neither list names the other.

So the order can be guessed from position, and that is all.

What would fix it

Any one of these, in preference order:

  1. Interleave server-side — return one ordered sequence per task, rather than
    history and artifacts as separate lists a caller has to reassemble.
  2. A per-entry sequence number on messages and artifacts, monotonic within a task.
  3. A per-entry timestamp, distinct from the task's status timestamp.

Any of the three lets a client render a task in the order it happened without
inferring anything.

Separately: the prose question is never persisted

When the agent parks on ask_user, the question also arrives as prose on the status
message, and the reader sees it during the turn. It is in neither history nor
artifacts afterwards, so it is gone on the next read. That is visible as a question
that sits at the foot of the transcript until a refresh, then vanishes -- and it means
a conversation replayed from ListTasks is missing the questions it was about.

Where the client stands meanwhile

ui/src/api/chat/a2aGrpcChatClient.ts (messagesFromTask) concatenates
history -> status message -> artifacts, which is what produces the ordering above. It
now interleaves by position as an approximation, and the note there points at this
issue. That approximation should be deleted once any of the three fixes lands.


🤖 written by Claude

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions