Skip to content

Commit 49e6c18

Browse files
Merge pull request #1590 from quifox:fix/skill-tool-instruction
PiperOrigin-RevId: 1007225661
2 parents 86f3130 + 9d68053 commit 49e6c18

2 files changed

Lines changed: 35 additions & 7 deletions

File tree

‎core/src/main/java/com/google/adk/tools/skills/SkillToolset.java‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@
3535
import java.util.Map;
3636
import java.util.StringJoiner;
3737

38-
/**
39-
* A toolset for managing and interacting with agent skills. Provides tools to list, load, and run
40-
* skills.
41-
*/
38+
/** A toolset for listing skills and loading their instructions and resources. */
4239
public class SkillToolset implements BaseToolset {
4340

4441
private static final String DEFAULT_SKILL_SYSTEM_INSTRUCTION =
@@ -49,21 +46,20 @@ public class SkillToolset implements BaseToolset {
4946
- **SKILL.md** (required): The main instruction file with skill metadata and detailed markdown instructions.
5047
- **references/** (Optional): Additional documentation or examples for skill usage.
5148
- **assets/** (Optional): Templates, scripts or other resources used by the skill.
52-
- **scripts/** (Optional): Executable scripts that can be run via bash.
49+
- **scripts/** (Optional): Scripts bundled with the skill. You cannot run them; use `load_skill_resource` to read one and follow it yourself.
5350
5451
This is very important:
5552
5653
1. If a skill seems relevant to the current user query, you MUST use the `load_skill` tool with `skill_name="<SKILL_NAME>"` to read its full instructions before proceeding.
5754
2. Once you have read the instructions, follow them exactly as documented before replying to the user. For example, If the instruction lists multiple steps, please make sure you complete all of them in order.
5855
3. The `load_skill_resource` tool is for viewing files within a skill's directory (e.g., `references/*`, `assets/*`, `scripts/*`). Do NOT use other tools to access these files.
59-
4. Use `run_skill_script` to run scripts from a skill's `scripts/` directory. Use `load_skill_resource` to view script content first if needed.
6056
""";
6157

6258
private final SkillSource skillSource;
6359
private final ImmutableList<BaseTool> coreTools;
6460
private final String systemInstruction;
6561

66-
/** Initializes the SkillToolset with a SkillSource and default execution settings. */
62+
/** Initializes the SkillToolset with a SkillSource and default system instructions. */
6763
public SkillToolset(SkillSource skillSource) {
6864
this(skillSource, DEFAULT_SKILL_SYSTEM_INSTRUCTION);
6965
}

‎core/src/test/java/com/google/adk/tools/skills/SkillToolsetTest.java‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.google.common.truth.Correspondence;
3232
import io.reactivex.rxjava3.core.Flowable;
3333
import java.util.List;
34+
import java.util.regex.Pattern;
3435
import org.junit.Test;
3536
import org.junit.runner.RunWith;
3637
import org.junit.runners.JUnit4;
@@ -140,4 +141,35 @@ public void close() {}
140141
baseToolset.processLlmRequest(LlmRequest.builder(), mock(ToolContext.class)).blockingAwait();
141142
}
142143
}
144+
145+
@Test
146+
public void processLlmRequest_defaultInstructionOnlyMentionsRegisteredTools() throws Exception {
147+
SkillSource skillSource =
148+
InMemorySkillSource.builder()
149+
.skill("test-skill")
150+
.frontmatter(Frontmatter.builder().name("test-skill").description("test skill").build())
151+
.instructions("Test instructions")
152+
.build();
153+
try (SkillToolset toolSet = new SkillToolset(skillSource)) {
154+
LlmRequest.Builder requestBuilder = LlmRequest.builder();
155+
toolSet.processLlmRequest(requestBuilder, mock(ToolContext.class)).blockingAwait();
156+
String instruction = requestBuilder.build().getSystemInstructions().get(0);
157+
assertThat(instruction)
158+
.contains(
159+
"Scripts bundled with the skill. You cannot run them; use `load_skill_resource` to"
160+
+ " read one and follow it yourself.");
161+
assertThat(instruction).doesNotContain("can be run via bash");
162+
List<String> availableTools =
163+
toolSet.getTools(null).toList().blockingGet().stream().map(BaseTool::name).toList();
164+
List<String> mentionedTools =
165+
Pattern.compile("`([a-z_]+)`")
166+
.matcher(instruction)
167+
.results()
168+
.map(match -> match.group(1))
169+
.distinct()
170+
.toList();
171+
assertThat(mentionedTools).isNotEmpty();
172+
assertThat(availableTools).containsAtLeastElementsIn(mentionedTools);
173+
}
174+
}
143175
}

0 commit comments

Comments
 (0)