Skip to content

fix(compat): apply v1.0 history_length semantics to v0.3 results - #1340

Open
D41910 wants to merge 1 commit into
a2aproject:mainfrom
D41910:fix/compat-history-length-zero
Open

D41910 wants to merge 1 commit into
a2aproject:mainfrom
D41910:fix/compat-history-length-zero

Conversation

@D41910

@D41910 D41910 commented Oct 15, 2026

Copy link
Copy Markdown

A v0.3 agent cannot be asked for an empty history, so the compat transports have to apply the v1.0 history_length semantics to the task they return.

Background

The two protocol versions disagree on history_length = 0:

  • v1.0 - 0 truncates the history to zero items; unlimited requires the field to be left unset (apply_history_length in src/a2a/utils/task.py).
  • v0.3 - 0 means unlimited. The repo already encodes this rule and tests it in tests/compat/v0_3/test_proto_utils.py::test_message_send_configuration_history_length ("A v0.3 history_length of 0 means unlimited, as in task_query_params"), and proto_utils.FromProto.task_query_params / FromProto.message_send_configuration already normalise 0 to None.

The gap

The compat client transports forward the caller's history_length to the v0.3 agent verbatim and then return whatever comes back:

  • rest_transport.get_task sends params['historyLength'] = request.history_length
  • jsonrpc_transport.get_task / send_message send the value produced by to_compat_get_task_request / to_compat_send_message_configuration
  • grpc_transport.get_task sends history_length=request.history_length

So a v1.0 caller that asks for history_length = 0 (i.e. no history) gets the entire history back from a v0.3 agent - the exact opposite of the request. history_length = N > 0 happens to work only because the v0.3 agent also does the truncation.

This is the outbound direction (v1.0 caller -> v0.3 agent). The inbound direction (v0.3 request -> v1.0 handler) is a separate fix in to_core_get_task_request / to_core_send_message_configuration, already covered by #1312, so this PR deliberately does not touch it.

Fix

Apply the existing apply_history_length helper to the converted task in get_task and send_message of the three compat transports. This is done on the result rather than on the request because v0.3 has no representation for "no history" - the transports ask for everything and then honour the v1.0 contract locally.

caller's history_length before after
unset full history full history (unchanged)
0 full history empty history
N > 0 last N last N (unchanged)

Tests

tests/compat/v0_3/test_history_length_compat.py covers get_task for all three transports with history_length of 0, 1 and unset, plus send_message for REST and JSON-RPC. Reverting the source change fails 8 of the 11 new tests; the 3 "unset keeps history" cases pass both ways and act as the control.

Full suite: uv run pytest -> 2286 passed, 183 skipped, 3 xfailed, 1 xpassed. The 4 errors under tests/integration/cross_version/client_server/ are environmental: they pass in isolation both with and without this change. ruff check and ruff format --check are clean.

AI disclosure

This change was produced with AI assistance and was checked against the specification and the existing tests cited above.

@D41910
D41910 requested a review from a team as a code owner October 15, 2026 01:54
@github-actions

Copy link
Copy Markdown

🧪 Code Coverage (vs main)

⬇️ Download Full Report

Base PR Delta
src/a2a/compat/v0_3/grpc_transport.py 63.64% 65.73% 🟢 +2.10%
src/a2a/compat/v0_3/jsonrpc_transport.py 75.23% 75.68% 🟢 +0.45%
src/a2a/compat/v0_3/proto_utils.py 90.57% 90.94% 🟢 +0.37%
src/a2a/server/cluster/database_event_stream.py 96.94% 92.86% 🔴 -4.08%
Total 93.17% 93.19% 🟢 +0.02%

Generated by coverage-comment.yml

@Iwaniukooo11 Iwaniukooo11 self-assigned this Oct 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants