fix(skills): prevent empty responses after load_skill#6226
Closed
lwangverizon wants to merge 1 commit into
Closed
Conversation
The skill system instruction does not tell the model what to do after a
load_skill call returns. Some models (notably Gemini) treat the load_skill
tool call as the entire turn and stop with no visible output, producing
empty responses. This is most acute for tool-heavy skills, whose next
correct action after load_skill is to call more tools rather than reply.
Add rule 7 to _build_skill_system_instruction: load_skill only retrieves
instructions and does NOT complete the turn; the model must continue in the
same turn (calling whatever tools the skill requires) and never end with an
empty response right after loading a skill. The rule uses the {prefix}
substitution like the other rules, so both the default and prefixed system
instructions carry it.
Verified in a production environment: appending this guidance dropped the
empty-response rate for Gemini after skill loading substantially.
Adds tests asserting rule 7 is present in both the default and prefixed
system instruction.
f247ec6 to
663b28b
Compare
copybara-service Bot
pushed a commit
that referenced
this pull request
Jun 30, 2026
Merge #6226 # fix(skills): prevent empty responses after `load_skill` Fixes #6225 ## Problem When an agent uses the skill tools, ADK appends a skill system instruction to the prompt (`_build_skill_system_instruction` in `src/google/adk/tools/skill_toolset.py`). The instruction does not tell the model what to do *after* a `load_skill` call returns. With Gemini models we observed a significant rate of **empty model responses** right after a `load_skill` call — the model loads the skill and ends its turn with no visible output. We saw this as a spike in empty responses in a Verizon production environment running ADK + Gemini, most acutely for tool-heavy skills whose next correct action after loading is to call more tools rather than reply. ## Change `_build_skill_system_instruction` only — covers both `DEFAULT_SKILL_SYSTEM_INSTRUCTION` and the per-toolset prefixed variant. **Add rule 7** (continue-after-load guard), appended after the existing rule 6: > 7. Loading a skill only retrieves its instructions; it does NOT complete your turn. > After a `load_skill` call returns, continue in the SAME turn: call whatever tools > the skill's steps require (search, data retrieval, render), then write your reply. > Never end your turn with an empty response right after loading a skill. No other rule is modified — rules 1–6 are left exactly as-is. The new rule uses the `{prefix}` substitution like the other rules (`{p}load_skill`), so the prefixed system instruction carries it too. ## Result This is the exact change we validated in production: appending rule 7 (rules 1–6 unchanged) dropped the empty-response rate for Gemini after skill loading substantially. ## Tests Adds focused tests in `tests/unittests/tools/test_skill_toolset.py`: - `test_system_instruction_marks_load_skill_as_non_terminal` — rule 7 present in the default instruction. - `test_prefixed_system_instruction_includes_continue_after_load_rule` — prefixed variant carries rule 7 with the prefix. Existing tests reference `DEFAULT_SKILL_SYSTEM_INSTRUCTION` by constant (not hardcoded text), so they are unaffected. ## Backwards compatibility Prompt-text-only, strictly additive change. No public API, signature, or existing-rule change. Co-authored-by: Yifan Wang <wanyif@google.com> COPYBARA_INTEGRATE_REVIEW=#6226 from lwangverizon:fix/skill-load-empty-response 663b28b PiperOrigin-RevId: 940550604
Collaborator
|
Thank you @lwangverizon for your contribution! 🎉 Your changes have been successfully imported and merged via Copybara in commit 7c79230. Closing this PR as the changes are now in the main branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(skills): prevent empty responses after
load_skillFixes #6225
Problem
When an agent uses the skill tools, ADK appends a skill system instruction to the
prompt (
_build_skill_system_instructioninsrc/google/adk/tools/skill_toolset.py). The instruction does not tell the modelwhat to do after a
load_skillcall returns. With Gemini models we observed asignificant rate of empty model responses right after a
load_skillcall — themodel loads the skill and ends its turn with no visible output.
We saw this as a spike in empty responses in a Verizon production environment running
ADK + Gemini, most acutely for tool-heavy skills whose next correct action after
loading is to call more tools rather than reply.
Change
_build_skill_system_instructiononly — covers bothDEFAULT_SKILL_SYSTEM_INSTRUCTIONand the per-toolset prefixed variant.
Add rule 7 (continue-after-load guard), appended after the existing rule 6:
No other rule is modified — rules 1–6 are left exactly as-is. The new rule uses the
{prefix}substitution like the other rules ({p}load_skill), so the prefixed systeminstruction carries it too.
Result
This is the exact change we validated in production: appending rule 7 (rules 1–6
unchanged) dropped the empty-response rate for Gemini after skill loading
substantially.
Tests
Adds focused tests in
tests/unittests/tools/test_skill_toolset.py:test_system_instruction_marks_load_skill_as_non_terminal— rule 7 present in thedefault instruction.
test_prefixed_system_instruction_includes_continue_after_load_rule— prefixedvariant carries rule 7 with the prefix.
Existing tests reference
DEFAULT_SKILL_SYSTEM_INSTRUCTIONby constant (not hardcodedtext), so they are unaffected.
Backwards compatibility
Prompt-text-only, strictly additive change. No public API, signature, or existing-rule
change.