fix(agent): keep explicit skills out of system prompt

This commit is contained in:
chengyongru
2026-08-19 18:40:20 +08:00
committed by chengyongru
parent ff674144d6
commit 8a2aa0821b
4 changed files with 63 additions and 23 deletions
+12 -7
View File
@@ -407,15 +407,20 @@ class TestBuildMessages:
builder = _builder(tmp_path)
messages = builder.build_messages([], "Please $review this patch and use $review carefully.")
plain_messages = builder.build_messages([], "Please review this patch carefully.")
system_prompt = messages[0]["content"]
assert "# Active Skills" in system_prompt
assert "### Skill: review" in system_prompt
assert "Follow the unique review checklist." in system_prompt
assert system_prompt.count("### Skill: review") == 1
assert messages[-1]["content"] == (
"Please $review this patch and use $review carefully."
)
user_prompt = messages[-1]["content"]
assert system_prompt == plain_messages[0]["content"]
assert "Follow the unique review checklist." not in system_prompt
assert "Please $review this patch" in user_prompt
assert "[Active Skills — instructions for this user turn]" in user_prompt
assert "### Skill: review" in user_prompt
assert "Follow the unique review checklist." in user_prompt
assert user_prompt.count("### Skill: review") == 1
assert messages[-1]["_meta"]["runtime_context"]["sources"] == [
"explicit_skills"
]
def test_unknown_skill_reference_does_not_change_active_skills(self, tmp_path):
messages = _builder(tmp_path).build_messages([], "Keep the shell literal $HOME.")
+15 -2
View File
@@ -146,6 +146,16 @@ async def test_runtime_context_is_persisted_as_next_turn_prompt_prefix(tmp_path)
from nanobot.bus.events import InboundMessage
from nanobot.bus.queue import MessageBus
skill_dir = tmp_path / "skills" / "review"
skill_dir.mkdir(parents=True)
(skill_dir / "SKILL.md").write_text(
"---\n"
"name: review\n"
"description: Review changes.\n"
"---\n\n"
"Follow the unique review checklist.",
encoding="utf-8",
)
provider = MagicMock()
provider.get_default_model.return_value = "test-model"
provider.generation = GenerationSettings()
@@ -169,7 +179,7 @@ async def test_runtime_context_is_persisted_as_next_turn_prompt_prefix(tmp_path)
channel="cli",
sender_id="user",
chat_id="direct",
content="first turn",
content="first turn $review",
))
await loop._process_message(InboundMessage(
channel="cli",
@@ -184,6 +194,9 @@ async def test_runtime_context_is_persisted_as_next_turn_prompt_prefix(tmp_path)
second_wire = LLMProvider._sanitize_empty_content(second_request)
assert second_wire[: len(first_wire)] == first_wire
assert first_wire[1] == second_wire[1]
assert first_wire[0] == second_wire[0]
assert "Follow the unique review checklist." not in first_wire[0]["content"]
assert "Follow the unique review checklist." in first_wire[1]["content"]
assert second_wire[2]["role"] == "assistant"
assert second_wire[2]["content"] == "first answer"
assert second_wire[3]["content"].startswith("second turn")
@@ -191,7 +204,7 @@ async def test_runtime_context_is_persisted_as_next_turn_prompt_prefix(tmp_path)
persisted_first_user = session.messages[0]
assert persisted_first_user["content"] == first_wire[1]["content"]
assert public_history_message(persisted_first_user)["content"] == "first turn"
assert public_history_message(persisted_first_user)["content"] == "first turn $review"
@pytest.mark.asyncio