Skip to content

fix(skills): prevent empty responses after load_skill#6226

Closed
lwangverizon wants to merge 1 commit into
google:mainfrom
lwangverizon:fix/skill-load-empty-response
Closed

fix(skills): prevent empty responses after load_skill#6226
lwangverizon wants to merge 1 commit into
google:mainfrom
lwangverizon:fix/skill-load-empty-response

Conversation

@lwangverizon

@lwangverizon lwangverizon commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

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:

  1. 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.

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.
@lwangverizon lwangverizon force-pushed the fix/skill-load-empty-response branch from f247ec6 to 663b28b Compare June 27, 2026 23:06
@wyf7107 wyf7107 self-assigned this Jun 29, 2026
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
@adk-bot

adk-bot commented Jun 30, 2026

Copy link
Copy Markdown
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.

@adk-bot adk-bot added the merged [Status] This PR is merged label Jun 30, 2026
@adk-bot adk-bot closed this Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged [Status] This PR is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Empty model responses after load_skill with Gemini (skill system instruction)

3 participants