Skip to content

fix(go-adk): surface the sub-agent's ask_user question in RemoteHitlHint - #2475

Merged
EItanya merged 3 commits into
kagent-dev:mainfrom
vramahandry:fix/remote-hitl-hint-ask-user-question
Sep 8, 2026
Merged

EItanya merged 3 commits into
kagent-dev:mainfrom
vramahandry:fix/remote-hitl-hint-ask-user-question

Conversation

@vramahandry

Copy link
Copy Markdown
Contributor

Summary

RemoteHitlHint() builds the hint text shown to a human when a sub-agent's own HITL pause bubbles up to the parent agent. Today it only lists the paused tool's name (e.g. ask_user) — never the actual question — even though AskUserRequest.Questions (already threaded through VisibleTools() into HitlTool.Args["questions"]) has the real content right there.

  • Before: "Remote agent 'github_agent' requires approval for tool(s): ask_user"
  • After: "Remote agent 'github_agent' asks: What is the GitHub owner/org for the repo?"

Real tool-approval hints (the non-ask_user case) are unaffected — same wording as before, existing TestBuildRemoteHitlStateAndHint still passes unchanged.

Discovered while building an external A2A chat bridge that correctly renders every other kagent HITL flow (direct tool approval, direct ask_user) from the same session — this was the one case where the confirmation card reaching a downstream A2A client carried no actionable information, because the hint itself never had it. Confirmed by inspecting the sub-agent's own ADK session directly (GET /api/sessions/<id>), where the real question is visible in adk_request_confirmation — it's just discarded before reaching RemoteHitlHint.

Fixes #2473

Changes

  • go/adk/pkg/a2a/hitl.go: new askUserQuestionText() helper extracts question text from an ask_user HitlTool's args; RemoteHitlHint() uses it when present, falling back to the existing tool-name-only wording otherwise.
  • go/adk/pkg/a2a/hitl_test.go: new TestBuildRemoteHitlStateAndHintAskUser covering the fixed behavior.

Test plan

  • go build ./adk/... — clean
  • go test ./adk/... — all packages pass (a2a, agent, app, tools, etc.)
  • gofmt -l / go vet ./adk/pkg/a2a/... — clean
  • Existing TestBuildRemoteHitlStateAndHint (tool-approval case) passes unchanged

@vramahandry
vramahandry force-pushed the fix/remote-hitl-hint-ask-user-question branch from be0a702 to eb714e3 Compare August 18, 2026 12:52
@github-actions github-actions Bot added the bug Something isn't working label Aug 18, 2026

@supreme-gg-gg supreme-gg-gg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix makes sense to me, two comments and this is ready to go

Comment thread go/adk/pkg/a2a/hitl.go Outdated
Comment thread go/adk/pkg/a2a/hitl_test.go
vramahandry added a commit to vramahandry/kagent that referenced this pull request Aug 19, 2026
askUserQuestionText() type-asserted a nested ask_user HitlTool's
Args["questions"] as []map[string]any, but Args round-trips through
JSON into a plain map[string]any, which decodes "questions" as []any
instead — silently dropping the question for nested (two-level)
ask_user pauses. AskUserRequest.Questions is already correctly typed
in both the direct and nested case (see BuildHITLStatusMessage), so
read it directly instead of re-deriving from VisibleTools() output.

Addresses review feedback from supreme-gg-gg on kagent-dev#2475.

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
@vramahandry
vramahandry force-pushed the fix/remote-hitl-hint-ask-user-question branch from eb714e3 to 9c3ac9e Compare August 19, 2026 08:12
supreme-gg-gg
supreme-gg-gg previously approved these changes Aug 19, 2026

@supreme-gg-gg supreme-gg-gg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks!

Comment thread go/adk/pkg/a2a/hitl.go Outdated
if state == nil {
return "Remote agent requires human input before continuing."
}
// AskUserRequest.Questions carries the real question text whether or not

@supreme-gg-gg supreme-gg-gg Aug 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this inline comment seems a bit too long (but not worth blocking on this)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed in 40bec6b, along with the similarly verbose comments added alongside it.

EItanya pushed a commit that referenced this pull request Aug 19, 2026
…hitl_hint (#2495)

## Summary

`remote_hitl_hint()` in the Python `kagent-adk` runtime builds the hint
text shown to a human when a sub-agent's own HITL pause bubbles up to
the parent agent. Unlike the Go runtime's `RemoteHitlHint()`, it only
ever lists the paused tool's *name* (e.g. `ask_user`) — never the actual
question — even though `AskUserRequest.questions` (set directly on the
request in `build_hitl_status_message`, whether or not `nested` is
populated) has the real content right there.

- Before: `"Remote agent 'github_agent' requires approval for tool(s):
ask_user"`
- After: `"Remote agent 'github_agent' asks: What is the GitHub
owner/org for the repo?"`

Real tool-approval hints (the non-`ask_user` case) are unaffected.

This is the Python-runtime counterpart to #2475, which fixed the same
class of bug in `go/adk/pkg/a2a/hitl.go`. The Go and Python runtimes
maintain independent implementations of this HITL hint logic, and the
Python side never had question-surfacing added — so a parent agent built
on `kagent-adk` still drops the question today even after #2475 merges.

Unlike the Go fix, there's no `[]any` vs `[]map[string]any]` JSON-decode
subtlety to worry about here: Pydantic's `HitlTool.args: dict[str, Any]`
keeps nested question dicts intact, so reading
`AskUserRequest.questions` directly is straightforward in both the
direct and nested case.

Fixes #2473

## Changes

- `python/packages/kagent-adk/src/kagent/adk/_hitl.py`:
`remote_hitl_hint()` now checks `AskUserRequest.questions` first and
returns `"Remote agent '{name}' asks: {question}"` when present, falling
back to the existing tool-name-only wording otherwise.
- `python/packages/kagent-adk/tests/unittests/test_hitl.py`: adds
`test_remote_hitl_hint_tool_approval`, `test_remote_hitl_hint_ask_user`,
and `test_remote_hitl_hint_ask_user_nested` (the last covering a
two-level nested `ask_user` pause).

## Test plan

- [x] `uv run pytest packages/kagent-adk/tests/unittests/test_hitl.py` —
18 passed (3 new)
- [x] `uv run ruff format --diff` / `uv run ruff check` — clean
- [x] Existing tests unaffected — no changes to tool-approval hint
wording

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
@supreme-gg-gg

Copy link
Copy Markdown
Contributor

@vramahandry this commit is not properly signed off: 40bec6b you need to do that for DCO to pass

@vramahandry
vramahandry force-pushed the fix/remote-hitl-hint-ask-user-question branch from 2675a2b to bc38318 Compare September 2, 2026 16:05
vramahandry added a commit to vramahandry/kagent that referenced this pull request Sep 2, 2026
…hitl_hint (kagent-dev#2495)

## Summary

`remote_hitl_hint()` in the Python `kagent-adk` runtime builds the hint
text shown to a human when a sub-agent's own HITL pause bubbles up to
the parent agent. Unlike the Go runtime's `RemoteHitlHint()`, it only
ever lists the paused tool's *name* (e.g. `ask_user`) — never the actual
question — even though `AskUserRequest.questions` (set directly on the
request in `build_hitl_status_message`, whether or not `nested` is
populated) has the real content right there.

- Before: `"Remote agent 'github_agent' requires approval for tool(s):
ask_user"`
- After: `"Remote agent 'github_agent' asks: What is the GitHub
owner/org for the repo?"`

Real tool-approval hints (the non-`ask_user` case) are unaffected.

This is the Python-runtime counterpart to kagent-dev#2475, which fixed the same
class of bug in `go/adk/pkg/a2a/hitl.go`. The Go and Python runtimes
maintain independent implementations of this HITL hint logic, and the
Python side never had question-surfacing added — so a parent agent built
on `kagent-adk` still drops the question today even after kagent-dev#2475 merges.

Unlike the Go fix, there's no `[]any` vs `[]map[string]any]` JSON-decode
subtlety to worry about here: Pydantic's `HitlTool.args: dict[str, Any]`
keeps nested question dicts intact, so reading
`AskUserRequest.questions` directly is straightforward in both the
direct and nested case.

Fixes kagent-dev#2473

## Changes

- `python/packages/kagent-adk/src/kagent/adk/_hitl.py`:
`remote_hitl_hint()` now checks `AskUserRequest.questions` first and
returns `"Remote agent '{name}' asks: {question}"` when present, falling
back to the existing tool-name-only wording otherwise.
- `python/packages/kagent-adk/tests/unittests/test_hitl.py`: adds
`test_remote_hitl_hint_tool_approval`, `test_remote_hitl_hint_ask_user`,
and `test_remote_hitl_hint_ask_user_nested` (the last covering a
two-level nested `ask_user` pause).

## Test plan

- [x] `uv run pytest packages/kagent-adk/tests/unittests/test_hitl.py` —
18 passed (3 new)
- [x] `uv run ruff format --diff` / `uv run ruff check` — clean
- [x] Existing tests unaffected — no changes to tool-approval hint
wording

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
@vramahandry
vramahandry force-pushed the fix/remote-hitl-hint-ask-user-question branch from bc38318 to 1b8ac72 Compare September 2, 2026 16:07
RemoteHitlHint() only listed the paused tool's name ('ask_user'), never
the actual question text, even though HitlTool.Args already carries it
via VisibleTools(). A human relayed a bubbled-up sub-agent HITL pause
saw 'requires approval for tool(s): ask_user' with no way to know what
was actually being asked.

Fixes kagent-dev#2473

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
askUserQuestionText() type-asserted a nested ask_user HitlTool's
Args["questions"] as []map[string]any, but Args round-trips through
JSON into a plain map[string]any, which decodes "questions" as []any
instead — silently dropping the question for nested (two-level)
ask_user pauses. AskUserRequest.Questions is already correctly typed
in both the direct and nested case (see BuildHITLStatusMessage), so
read it directly instead of re-deriving from VisibleTools() output.

Addresses review feedback from supreme-gg-gg on kagent-dev#2475.

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
supreme-gg-gg flagged the inline comment as too long; tightened it and
the similarly verbose doc/test comments added in the same change while
keeping the JSON round-trip explanation.

Signed-off-by: Vivien Ramahandry <56304555+vramahandry@users.noreply.github.com>
@vramahandry
vramahandry force-pushed the fix/remote-hitl-hint-ask-user-question branch from 1b8ac72 to 3a338cf Compare September 2, 2026 16:08
@vramahandry

vramahandry commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Hello @supreme-gg-gg , sorry I forgot the DCO.
Now it seems ok. Thank you !

@vramahandry

Copy link
Copy Markdown
Contributor Author

Hello @supreme-gg-gg is there any issue of not being merged ?

@EItanya
EItanya added this pull request to the merge queue Sep 8, 2026
Merged via the queue into kagent-dev:main with commit 9e67435 Sep 8, 2026
25 checks passed
@vramahandry

Copy link
Copy Markdown
Contributor Author

Hello @EItanya do you know when it will be released to a tagged version ?

@EItanya

EItanya commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Hello @EItanya do you know when it will be released to a tagged version ?

If you need this on 0.10 you will need to backport it. Hopefully we'll be starting beta releases on main early next week

@vramahandry

Copy link
Copy Markdown
Contributor Author

Hello @EItanya do you know when it will be released to a tagged version ?

If you need this on 0.10 you will need to backport it. Hopefully we'll be starting beta releases on main early next week

How I can backport myself ? Do I create a new tag on my fork from the latest tag v0.10.1 ?

@EItanya

EItanya commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Hello @EItanya do you know when it will be released to a tagged version ?

If you need this on 0.10 you will need to backport it. Hopefully we'll be starting beta releases on main early next week

How I can backport myself ? Do I create a new tag on my fork from the latest tag v0.10.1 ?

Open a PR against release-v0.10.x

@vramahandry

vramahandry commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Hello @EItanya,
Looked into backporting this (and #2495) to release/v0.10.x. Not straightforward, unfortunately: both fixes sit on top of #2396 (A2A HITL extension rewrite), which itself depends on #2354 (A2A v1.0 migration) — neither of which was ever backported to release/v0.10.x. That branch still runs the pre-extension HITL model (adk_request_confirmation DataParts), so _hitl.py / the current hitl.go don't exist there in a form these commits can apply to.

Tried cherry-picking #2396 alone onto release/v0.10.x as a test — 20+ conflicting files across Go, Python, and the UI (agent executor, remote A2A tool, event converter, the whole chat UI). It's a real architecture migration, not a mechanical backport.

If this is needed on 0.10.x, the options are either porting the A2A v1.0 + HITL extension migration itself (multi-day effort, real risk to the release branch), or a small hand-written fix against the old adk_request_confirmation hint logic that gets the same user-visible result without the migration.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] RemoteHitlHint drops the sub-agent's actual ask_user question, only names the tool

3 participants