Skip to content

[BUG]: A2A conversation history omits assistant turns — follow-up messages don't see prior answers #368

Description

@teriyakichild

Ref: #325, #328

Summary

A follow-up A2A message on an existing contextId is given the prior user turns but never the agent's own responses. Every follow-up therefore behaves as if it has never spoken.

Observed against aura-web-server with A2A enabled:

task 1 (user): "In exactly three sentences, explain what a log pipeline is."
               -> completes, answers correctly

task 2 (user, same contextId): "How many sentences did you just use?"
               -> "I haven't responded to that prompt yet, so I used zero sentences."

Expected: the follow-up sees the previous assistant answer and replies "three".

Root cause

get_history_for_context (crates/aura-web-server/src/a2a/agent_executor.rs:549) rebuilds history by listing tasks for the context and flat-mapping each task's history field:

let chat_history: Vec<aura::Message> = task_history
    .into_iter()
    .flat_map(|t| t.history.unwrap())
    .filter_map(|m| convert_a2a_msg_to_aura(&m))
    .collect();

The context lookup itself works — list(context_id) returns every task in the conversation. The problem is what lives in task.history: the agent's response is written to artifacts, not to history. A completed task looks like this:

status: TASK_STATE_COMPLETED
history messages: 1
   role=ROLE_USER   text="In exactly three sentences, explain what a log pipeline is."
artifacts: [("response", 84 parts), ("final", 1 part)]

ROLE_AGENT present in history? False

So flat_map(|t| t.history) can only ever yield user turns. convert_a2a_msg_to_aura has a Role::Agent => Message::assistant(...) arm that is unreachable in practice.

The same call also passes include_artifacts: Some(false), so the assistant text is not even fetched from the store.

Reproduction

Pre-requisites

  • aura-web-server running with --enable-a2a and any single-agent config (no HITL gating).

Steps

  1. Send a first message and note task.contextId:
curl -s -X POST http://localhost:8080/a2a/v1/message:send \
  -H "Content-Type: application/json" -H "x-aura-model: <agent-alias>" \
  -d '{"message":{"messageId":"m1","role":"ROLE_USER","parts":[{"text":"In exactly three sentences, explain what a log pipeline is."}]}}'
  1. Poll GET /a2a/v1/tasks/{id} until TASK_STATE_COMPLETED. Note that history holds only the ROLE_USER message while the answer sits in the response artifact.

  2. Send a follow-up on the same contextId:

curl -s -X POST http://localhost:8080/a2a/v1/message:send \
  -H "Content-Type: application/json" -H "x-aura-model: <agent-alias>" \
  -d '{"message":{"messageId":"m2","contextId":"<CTX>","role":"ROLE_USER","parts":[{"text":"How many sentences did you just use?"}]}}'
  1. Poll it. The answer denies having responded.

Why the existing test does not catch this

test_sequential_tasks_share_context (crates/aura-web-server/tests/a2a_test.rs:713) passes, because the only thing it asserts is that task 2 can recall what was asked in task 1:

task 1 (user): "Call mock_tool with message='context-test-{uuid}'. Do not say anything else."
task 2 (user): "Tell me what was asked in the first call for this context."
assert: response contains "context-test-{uuid}"

That UUID originates in task 1's user message — the half of history that does carry. The test validates the user-turn path and is blind to the missing assistant turns.

The test's own comment states the expectation that is currently false:

// Wait for task 1 to complete so its full history (tool call, tool result,
// assistant response) is persisted in the task store before task 2 starts.

Tool calls, tool results, and assistant responses are not in task.history.

Suggested fix

Reconstruct the assistant turn from the task's response artifact (requiring include_artifacts: Some(true) in the ListTasksRequest), or write the agent's final message into task.history as ROLE_AGENT when the task completes.

Whichever way, extend test_sequential_tasks_share_context (or add a sibling) to assert on something only the assistant turn could supply — the current phrasing passes without it.

Scope note

Pre-existing, not a regression. git diff main..feature/GH-327-session-storage-trait-and-in-memory touches only shared_task_store.rs under crates/aura-web-server/src/a2a/; get_history_for_context dates to 349014dc feat(a2a): initial implementation.

Relevant to the session-storage roadmap: #328 (Redis/Valkey A2A task store) is motivated partly by making "conversation history by context_id survive load-balancing". Making that history durable and cross-pod will not help while the assistant half of every exchange never reaches the store. Worth fixing before or alongside #328.

Activity

  1. added a commit that references this issue on Aug 11, 2026
    c579bfb
  2. added a commit that references this issue on Aug 13, 2026
    72f1e8c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions