Skip to content

Commit e67934b

Browse files
authored
fix: add history length and page size validations (#726)
# Description See [here](https://a2a-protocol.org/latest/specification/#validation-error-example) and [3.1.4. List Tasks](https://a2a-protocol.org/latest/specification/#314-list-tasks). Re #515
1 parent 1d328e1 commit e67934b

4 files changed

Lines changed: 146 additions & 43 deletions

File tree

src/a2a/server/request_handlers/default_request_handler.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@
5252
TaskNotFoundError,
5353
UnsupportedOperationError,
5454
)
55-
from a2a.utils.task import apply_history_length
55+
from a2a.utils.task import (
56+
apply_history_length,
57+
validate_history_length,
58+
validate_page_size,
59+
)
5660
from a2a.utils.telemetry import SpanKind, trace_class
5761

5862

@@ -122,6 +126,8 @@ async def on_get_task(
122126
context: ServerCallContext | None = None,
123127
) -> Task | None:
124128
"""Default handler for 'tasks/get'."""
129+
validate_history_length(params)
130+
125131
task_id = params.id
126132
task: Task | None = await self.task_store.get(task_id, context)
127133
if not task:
@@ -135,6 +141,10 @@ async def on_list_tasks(
135141
context: ServerCallContext | None = None,
136142
) -> ListTasksResponse:
137143
"""Default handler for 'tasks/list'."""
144+
validate_history_length(params)
145+
if params.HasField('page_size'):
146+
validate_page_size(params.page_size)
147+
138148
page = await self.task_store.list(params, context)
139149
for task in page.tasks:
140150
if not params.include_artifacts:
@@ -327,6 +337,8 @@ async def on_message_send(
327337
Starts the agent execution for the message and waits for the final
328338
result (Task or Message).
329339
"""
340+
validate_history_length(params.configuration)
341+
330342
(
331343
_task_manager,
332344
task_id,

src/a2a/utils/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
DEFAULT_LIST_TASKS_PAGE_SIZE = 50
88
"""Default page size for the `tasks/list` method."""
99

10+
MAX_LIST_TASKS_PAGE_SIZE = 100
11+
"""Maximum page size for the `tasks/list` method."""
12+
1013

1114
# Transport protocol constants
1215
# These match the protocol binding values used in AgentCard

src/a2a/utils/task.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
TaskState,
1414
TaskStatus,
1515
)
16+
from a2a.utils.constants import MAX_LIST_TASKS_PAGE_SIZE
17+
from a2a.utils.errors import InvalidParamsError, ServerError
1618

1719

1820
def new_task(request: Message) -> Task:
@@ -96,6 +98,16 @@ def HasField(self, field_name: Literal['history_length']) -> bool: # noqa: N802
9698
...
9799

98100

101+
def validate_history_length(config: HistoryLengthConfig | None) -> None:
102+
"""Validates that history_length is non-negative."""
103+
if config and config.history_length < 0:
104+
raise ServerError(
105+
error=InvalidParamsError(
106+
message='history length must be non-negative'
107+
)
108+
)
109+
110+
99111
def apply_history_length(
100112
task: Task, config: HistoryLengthConfig | None
101113
) -> Task:
@@ -136,6 +148,24 @@ def apply_history_length(
136148
return task
137149

138150

151+
def validate_page_size(page_size: int) -> None:
152+
"""Validates that page_size is in range [1, 100].
153+
154+
See Also:
155+
https://a2a-protocol.org/latest/specification/#314-list-tasks
156+
"""
157+
if page_size < 1:
158+
raise ServerError(
159+
error=InvalidParamsError(message='minimum page size is 1')
160+
)
161+
if page_size > MAX_LIST_TASKS_PAGE_SIZE:
162+
raise ServerError(
163+
error=InvalidParamsError(
164+
message=f'maximum page size is {MAX_LIST_TASKS_PAGE_SIZE}'
165+
)
166+
)
167+
168+
139169
_ENCODING = 'utf-8'
140170

141171

0 commit comments

Comments
 (0)