Skip to content

list_skills tool call incorrectly sets is_final=True, causing premature agent termination #6907

Description

@witlong

Issue Title: list_skills tool call incorrectly sets is_final=True, prematurely terminating agent execution
🔴 Required Information
Is your feature request related to a specific problem?
Yes. When an agent uses the list_skills tool (provided by SkillToolset), the event returned immediately has is_final=True, which causes the agent invocation to terminate prematurely. This prevents the agent from performing any subsequent actions after listing available skills.

Debug Log:

text
[Event] Author: ___agent_5, Type: Event, Final: True, Content: parts=[
Part(text='好的,llm-wiki skill 已经加载完成。现在我需要调用 list_skills 来获取所有可用的 skills 列表,然后将结果保存到 list_skills_out.txt 文件中。', thought=True),
Part(text='<tool_call>list_skills</tool_call>')
] role='model' is_final=True
As shown above, immediately after the list_skills tool call is emitted, the event is marked as is_final=True, halting the agent's execution flow.

In contrast, other skill-related tools such as load_skill, load_skill_resource, and run_skill_script behave correctly—they do not set is_final=True after a single call, allowing the agent to continue execution and chain multiple tool calls together.

Describe the Solution You'd Like
list_skills should behave consistently with other skill tools (load_skill, load_skill_resource, run_skill_script). It should not set is_final=True immediately after a single tool call. Instead, the agent should be able to:

Call list_skills to obtain the available skills metadata

Continue execution to parse the results

Optionally call load_skill to load a specific skill's instructions

Perform subsequent actions based on the skill information

The is_final flag should only be set to True when the agent has genuinely completed its task, not merely after a query-type tool call.

Impact on your work
This issue blocks the creation of workflows that require:

Listing available skills and then performing actions based on the results

Loading a skill after confirming its existence via list_skills

Any multi-step skill-based automation

This is critical for our implementation as we rely on the Skills system for progressive disclosure of tool capabilities. We need this resolved to build production-grade agents that can dynamically discover and use skills.

Willingness to contribute
Yes, if provided with guidance on where to look in the codebase and potential approaches to fix this issue.

🟡 Recommended Information
Describe Alternatives You've Considered
Workaround attempted: Explicitly instructing the agent in system prompts to ask follow-up questions after calling list_skills to avoid termination. This does not work, as the is_final flag appears to be set at the framework level, not driven by LLM decision-making.

Workaround attempted: Bypassing list_skills and hardcoding skill names to use load_skill directly. This is not scalable for dynamic skill discovery and defeats the purpose of the progressive disclosure system.

Workaround attempted: Parsing skill metadata from filesystem manually outside the ADK framework. This requires duplicating framework functionality and introduces maintenance overhead.

Proposed API / Implementation
My suspicion is that in the SkillToolset or the underlying tool invocation handling logic, the framework treats any tool that returns a function_response as a "final" action if no additional function_calls are scheduled.

Potential fix areas to investigate:

The SkillToolset class implementation (likely in google/adk-python repository)

The event/response handling logic that determines when is_final should be set

Whether list_skills should be treated as a "discovery" tool that should not trigger termination

Pseudo-code of expected behavior:

python

Current problematic behavior

agent.invoke("list all skills")

-> Event(is_final=True) immediately after tool call

Expected behavior

agent.invoke("list all skills, then load the first one")

-> Event(function_call: list_skills)

-> Event(function_response: list_skills results) # is_final=False

-> Event(function_call: load_skill) # continues execution

-> Event(...) # continues

-> Event(is_final=True) # only when truly done

Additional Context
Framework version: google-adk (latest as of August 2026)

Feature status: The official documentation marks Skills as "Experimental"

Related observations: load_skill, load_skill_resource, and run_skill_script all work correctly (do not set is_final=True)

This appears to be a framework-level behavior issue, not a model/LLM decision issue, as the is_final flag is being set by the framework before the model has a chance to decide on next actions

This issue may be related to how the framework handles function_response events for tools that don't return structured "tool call" follow-ups in the same response cycle.

Metadata

Metadata

Labels

tools[Component] This issue is related to tools

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions