From c739088d62b9e3589f6a5f9bb31cdc73688ca20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=B0=E4=B9=8B?= Date: Tue, 5 May 2026 10:51:31 +0800 Subject: [PATCH] fix(agents): enforce exact skill path from [AI-assisted] (#74161) Summary: - The PR updates agents skill prompt guidance to require exact `` paths for single- and multi-skill selection, adds prompt assertions, and records the fix in the changelog. - Reproducibility: yes. Static source reproduction is enough: current main lacks the exact-`` guard ... illsSection()`, while the PR diff adds it to both selection branches and asserts the resulting prompt text. Automerge notes: - PR branch already contained follow-up commit before automerge: fix: enforce exact skill paths for all skill matches Validation: - ClawSweeper review passed for head 743c9840c117312646ff6065ce4939f6555c5c0b. - Required merge gates passed before the squash merge. Prepared head SHA: 743c9840c117312646ff6065ce4939f6555c5c0b Review: https://github.com/openclaw/openclaw/pull/74161#issuecomment-4341488109 Co-authored-by: tianguicheng Co-authored-by: sallyom --- CHANGELOG.md | 1 + src/agents/system-prompt.test.ts | 10 ++++++++-- src/agents/system-prompt.ts | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d1375eaa32..545cfd0bbd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1398,6 +1398,7 @@ Docs: https://docs.openclaw.ai - Gateway/plugins: enable the native `require()` fast path on Windows for bundled plugin modules so plugin loading uses `require()` instead of Jiti's transform pipeline, reducing startup from ~39s to ~2s on typical 6-plugin setups. Fixes #68656. (#74173) Thanks @galiniliev. - macOS app: detect stale Gateway TLS certificate pins, automatically repair trusted Tailscale Serve rotations, and surface paired-but-disconnected Mac companion nodes so partial Gateway connections no longer look healthy. Thanks @guti. - Feishu: recreate WebSocket clients with monitor-owned backoff only after SDK reconnect exhaustion, preserving heartbeat defaults and shutdown cleanup without treating recoverable SDK callback errors as terminal, so persistent connections recover without manual gateway restart. Fixes #52618; duplicate evidence #59753; related #55532, #68766, #72411, and #73739. Thanks @vincentkoc, @schumilin, @alex-xuweilong, @120106835, @sirfengyu, and @tianhaocui. +- Agents/skills: require exact `` skill paths for both single-skill and multi-skill prompt selection, so agents do not guess or hard-code skill file paths. (#74161) Thanks @lanzhi-lee. ## 2026.4.27 diff --git a/src/agents/system-prompt.test.ts b/src/agents/system-prompt.test.ts index 0a36cbca762..73cef69d7f3 100644 --- a/src/agents/system-prompt.test.ts +++ b/src/agents/system-prompt.test.ts @@ -458,7 +458,10 @@ describe("buildAgentSystemPrompt", () => { expect(prompt).toContain("- Read: Read file contents"); expect(prompt).toContain("- Exec: Run shell commands"); expect(prompt).toContain( - "- If exactly one skill clearly applies: read its SKILL.md at with `Read`, then follow it.", + "- If exactly one skill clearly applies: read its SKILL.md at with `Read`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.", + ); + expect(prompt).toContain( + "- If multiple could apply: choose the most specific one, read its SKILL.md at with `Read`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.", ); expect(prompt).toContain("OpenClaw docs: /tmp/openclaw/docs"); expect(prompt).toContain( @@ -644,7 +647,10 @@ describe("buildAgentSystemPrompt", () => { expect(prompt).toContain("## Skills"); expect(prompt).toContain( - "- If exactly one skill clearly applies: read its SKILL.md at with `read`, then follow it.", + "- If exactly one skill clearly applies: read its SKILL.md at with `read`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.", + ); + expect(prompt).toContain( + "- If multiple could apply: choose the most specific one, read its SKILL.md at with `read`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.", ); }); diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index 9d87d2a2b3f..1078c7057ed 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -202,8 +202,8 @@ function buildSkillsSection(params: { skillsPrompt?: string; readToolName: strin return [ "## Skills (mandatory)", "Before replying: scan entries.", - `- If exactly one skill clearly applies: read its SKILL.md at with \`${params.readToolName}\`, then follow it.`, - "- If multiple could apply: choose the most specific one, then read/follow it.", + `- If exactly one skill clearly applies: read its SKILL.md at with \`${params.readToolName}\`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.`, + `- If multiple could apply: choose the most specific one, read its SKILL.md at with \`${params.readToolName}\`, then follow it. You MUST use the exact value from ; never guess, fabricate, or hard-code a skill file path.`, "- If none clearly apply: do not read any SKILL.md.", "Constraints: never read more than one skill up front; only read after selecting.", "- When a skill drives external API writes, assume rate limits: prefer fewer larger writes, avoid tight one-item loops, serialize bursts when possible, and respect 429/Retry-After.",