Skip to content

fix: use toolConfirmation.payload as submit payload instead of tool args#440

Open
vietnamesekid wants to merge 1 commit into
google:mainfrom
vietnamesekid:fix/confirmation-form-uses-tool-args-instead-of-payload
Open

fix: use toolConfirmation.payload as submit payload instead of tool args#440
vietnamesekid wants to merge 1 commit into
google:mainfrom
vietnamesekid:fix/confirmation-form-uses-tool-args-instead-of-payload

Conversation

@vietnamesekid
Copy link
Copy Markdown

@vietnamesekid vietnamesekid commented May 15, 2026

Fixes #439

Problem

I was following the official docs at https://adk.dev/tools-custom/confirmation/#confirmation-definition
to implement a custom confirmation flow. When submitting the confirmation form, the agent
receives { days: 5 } (the tool's original args) instead of { approved_days: 0 } (the
payload schema defined by the developer), causing a KeyError crash.

Root Cause

In long-running-response.ts, initForm() initializes confirmationModel.payload from
originalFunctionCall.args instead of toolConfirmation.payload. Since onSend() reads
confirmationModel.payload to build the submit request, the wrong payload gets sent.

Fix

Read toolConfirmation.payload first when initializing confirmationModel.payload, with
a fallback to originalFunctionCall.args for cases where the developer did not provide a payload.

// before
this.confirmationModel.payload = JSON.stringify(
  this.functionCall.args?.originalFunctionCall?.args || {}, null, 2
);

// after
this.confirmationModel.payload = JSON.stringify(
  this.functionCall.args?.toolConfirmation?.payload ??
  this.functionCall.args?.originalFunctionCall?.args ??
  {}, null, 2
);

@vietnamesekid
Copy link
Copy Markdown
Author

this.functionCall.args?.toolConfirmation?.payload is safe to read here because the backend always includes it when the developer provides a payload.

In adk-python/flows/llm_flows/functions.py, the adk_request_confirmation event is built with:

request_confirmation_function_call = types.FunctionCall(
    name=REQUEST_CONFIRMATION_FUNCTION_CALL_NAME,
    args={
        'originalFunctionCall': original_function_call.model_dump(...),
        'toolConfirmation': tool_confirmation.model_dump(by_alias=True, exclude_none=True),
    },
)

And ToolConfirmation is defined as:

class ToolConfirmation(BaseModel):
    hint: str = ""
    confirmed: bool = False
    payload: Optional[Any] = None

So when the developer calls tool_context.request_confirmation(payload={...}), payload is non-None and survives exclude_none=True, meaning toolConfirmation.payload will always be present in the event sent to the UI. The fallback to originalFunctionCall.args only kicks in when the developer did not provide a payload at all.

@vietnamesekid vietnamesekid changed the title fix: confirmation form renders toolConfirmation.payload instead of tool args fix: use toolConfirmation.payload as submit payload instead of tool args May 15, 2026
…ol args

The confirmation form was reading originalFunctionCall.args to populate
the payload field, causing the agent to receive the wrong keys and crash
with KeyError when it expected the payload schema defined by the developer.

Now reads toolConfirmation.payload with a fallback to originalFunctionCall.args
for cases where no payload is provided.

Fixes google#439
@vietnamesekid vietnamesekid force-pushed the fix/confirmation-form-uses-tool-args-instead-of-payload branch from 3564bc8 to b94e643 Compare May 15, 2026 07:50
@vietnamesekid
Copy link
Copy Markdown
Author

vietnamesekid commented May 15, 2026

Tested with different payload schemas both {'approved_days': days} and {'days': days} work correctly after this fix. The submitted payload now always matches whatever schema the developer defines in request_confirmation(payload={...}) regardless of the key names

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.

Web UI sends tool args instead of confirmation payload, crashing the agent

1 participant