Skip to content

A2A: an input-required prompt in a data part is not turned into a function call on a2a-sdk 1.x #7952

Open

Description

@hyeonsang010716

🔴 Required Information

Describe the Bug:
When a remote agent asks for user input (input-required or auth-required), _create_mock_function_call_for_required_user_input replaces the prompt part with a mock function call and marks it long-running, so the caller sees the request for input. A prompt sent as a data part reaches it as the inline blob made by _compat.data_part_blob_bytes, and _extract_user_input_prompt reads that blob with data_part.get("data").

That matches the 0.3.x blob, which is the whole serialized DataPart ({"kind": "data", "data": {...}}). On a2a-sdk 1.x the blob is only the data itself, so:

  • A data prompt is not turned into a function call. The event keeps the raw <a2a_datapart_json>...</a2a_datapart_json> blob and has no long_running_tool_ids, so the caller gets no request for input.
  • A data prompt that has its own "data" key is turned into a function call with only that value as the prompt.

A text prompt is not affected, and on 0.3.x both cases work.

Steps to Reproduce:

  1. Install a2a-sdk 1.x.
  2. Run the code below.

Expected Behavior:
Each prompt becomes the mock function call, with the data part's data as the prompt.

{'input_required': 'Approve the refund?'} True
{'input_required': {'question': 'Approve the refund?'}} True
{'input_required': {'kind': 'approval', 'data': 'refund-42'}} True

Observed Behavior:

{'input_required': 'Approve the refund?'} True
b'<a2a_datapart_json>{"question": "Approve the refund?"}</a2a_datapart_json>' False
{'input_required': 'refund-42'} True

Environment Details:

  • ADK Library Version (pip show google-adk): 2.13.0 (also on main at 6b01717)
  • a2a-sdk: 1.1.2
  • Desktop OS: macOS
  • Python Version (python -V): 3.14.7

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A (no model call is needed to reproduce)

🟡 Optional Information

Additional Context:
test_convert_a2a_task_to_event_data_part_input_required passes on 1.x because it replaces the part converter with a mock that returns a blob in the 0.3.x layout, so the 1.x layout is never converted there.

Through RemoteA2aAgent and a Runner, the next user message still continues the same remote task, since that follows the task state. What is missing is the mock function call and long_running_tool_ids on the event.

Minimal Reproduction Code:

from a2a.types import Message
from a2a.types import Part
from a2a.types import Role
from a2a.types import Task
from a2a.types import TaskState
from a2a.types import TaskStatus
from google.adk.a2a.converters.to_adk_event import convert_a2a_task_to_event
from google.protobuf.json_format import ParseDict
from google.protobuf.struct_pb2 import Value


def input_required_task(part: Part) -> Task:
  return Task(
      id="task-1",
      context_id="context-1",
      status=TaskStatus(
          state=TaskState.TASK_STATE_INPUT_REQUIRED,
          message=Message(
              message_id="m1", role=Role.ROLE_AGENT, parts=[part]
          ),
      ),
  )


for part in (
    Part(text="Approve the refund?"),
    Part(data=ParseDict({"question": "Approve the refund?"}, Value())),
    Part(data=ParseDict({"data": "refund-42", "kind": "approval"}, Value())),
):
  event = convert_a2a_task_to_event(input_required_task(part), author="remote")
  adk_part = event.content.parts[0]
  print(
      adk_part.function_call.args
      if adk_part.function_call
      else adk_part.inline_data.data,
      bool(event.long_running_tool_ids),
  )

How often has this issue occurred?:

  • Always (100%)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions