Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0e6d3fc
fix(a2a): make the client reconcile artifacts by identity and raise o…
vvlrff Oct 24, 2026
f5ca6e1
fix(a2a): honor full artifact replacements and finished-task resubscribe
vvlrff Oct 26, 2026
b65e1f3
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 26, 2026
a018adb
feat(a2a): enhance artifact handling and event collection in client a…
vvlrff Oct 26, 2026
c53c874
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 26, 2026
44b54e8
fix(a2a): keep a tool-call artifact open until its last chunk
vvlrff Oct 26, 2026
f4059bc
fix(a2a): honor last_chunk for tool-call artifacts and resubscribe sn…
vvlrff Oct 27, 2026
081bbba
test(a2a): script served agents with TestConfig via ToolRoundsConfig
vvlrff Oct 27, 2026
fcb07d7
fix(a2a): settle tasks from snapshots and make cancel racing completi…
vvlrff Oct 28, 2026
8244adb
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 28, 2026
004742c
fix(a2a): serialize task transitions and keep only this turn's text f…
vvlrff Oct 28, 2026
f7513b0
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 28, 2026
da6a15e
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 28, 2026
199c9c9
fix(a2a): notify lifecycle observers outside the transition lock
Lancetnik Oct 29, 2026
d4aa8e2
fix(a2a): order lifecycle delivery and complete wire commits on cancel
Lancetnik Oct 29, 2026
4a0361b
fix(a2a): stop dropping or doubling client tool calls and replies, is…
vvlrff Oct 30, 2026
d31005c
fix(a2a): refresh HITL turn state and release lifecycle observers
Lancetnik Oct 30, 2026
016ccd0
fix(a2a): reconcile artifacts changed after last_chunk with the store…
vvlrff Oct 31, 2026
52083c4
fix(a2a): return unstreamed answers as artifacts and fill required ca…
vvlrff Oct 31, 2026
59d76b0
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 31, 2026
96d6e7f
Merge branch 'main' into fix/a2a-client-conformance
vvlrff Oct 31, 2026
044ceb3
Merge main into fix/a2a-client-conformance
Lancetnik Nov 1, 2026
2ac26e3
fix(a2a): clear replaced text before client tool continuations
Lancetnik Nov 1, 2026
bd3e482
fix(a2a): preserve complete artifacts in streamed task errors
Lancetnik Nov 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ag2/a2a/_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ async def open_session(config: A2AConfig) -> AsyncGenerator[tuple[Client, Client
card=card,
httpx_client=httpx_client,
streaming=False,
interface=iface,
transport=transport,
interceptors=tuple(config.interceptors),
grpc_channel_factory=config.grpc_channel_factory,
Expand Down
22 changes: 22 additions & 0 deletions ag2/a2a/_states.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2026, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
#
# SPDX-License-Identifier: Apache-2.0

from a2a.types import TaskState

# The spec's terminal states (§4.1.3): the task accepts nothing further.
TERMINAL_STATES = frozenset({
TaskState.TASK_STATE_COMPLETED,
TaskState.TASK_STATE_CANCELED,
TaskState.TASK_STATE_FAILED,
TaskState.TASK_STATE_REJECTED,
})

# The interrupted states (§4.1.3): the task hands control back to the caller.
INTERRUPTED_STATES = frozenset({
TaskState.TASK_STATE_INPUT_REQUIRED,
TaskState.TASK_STATE_AUTH_REQUIRED,
})

# States after which nothing more arrives for the current turn.
SETTLED_STATES = TERMINAL_STATES | INTERRUPTED_STATES
12 changes: 8 additions & 4 deletions ag2/a2a/card.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def build_card(
if "grpc" in transports and grpc_url is None:
raise ValueError("grpc_url is required when 'grpc' is in transports")

description_text = description or _agent_description(agent)
# Spec §5.7: the card's description is REQUIRED, so an agent without a prompt is described by its name.
description_text = description or _agent_description(agent) or agent.name
resolved_skills = _resolve_skills(agent, skills, description_text)
declared: list[AgentExtension] = [
AgentExtension(
Expand Down Expand Up @@ -202,7 +203,10 @@ def _resolve_skills(
return list(explicit)

auto = [
AgentSkill(id=skill.name, name=skill.name, description=skill.metadata.description or skill.name)
# ``tags`` is REQUIRED (spec §5.7); a skill's own name is the one keyword it is sure to have.
AgentSkill(
id=skill.name, name=skill.name, description=skill.metadata.description or skill.name, tags=[skill.name]
)
for tool in agent.tools
if isinstance(tool, SkillsToolkit)
for skill in tool.merged_skills()
Expand All @@ -214,7 +218,7 @@ def _resolve_skills(
AgentSkill(
id=agent.name,
name=agent.name,
description=description or agent.name,
tags=[],
description=description,
tags=[agent.name],
),
]
Loading
Loading