From 34e8f97b1f420ae2152db9a36d613bf0618dbb1c Mon Sep 17 00:00:00 2001 From: chengyongru <2755839590@qq.com> Date: Sat, 18 Apr 2026 17:50:11 +0800 Subject: [PATCH] refactor(templates): separate identity and SOUL responsibilities Move all behavioral instructions out of identity.md into SOUL.md so that each file has a single clear purpose: - identity.md: capability facts only (runtime, workspace, format hints, tool guidance, untrusted content warning) - SOUL.md: behavioral rules (name, personality, execution rules) The "Act, don't narrate" rule is refined into layered behavior: act immediately on single-step tasks, plan first for multi-step tasks. This eliminates the contradiction where identity said "never end with a plan" but user SOUL.md said "always plan first". --- nanobot/templates/SOUL.md | 21 +++++++++++++----- nanobot/templates/agent/identity.md | 14 +----------- tests/agent/test_context_prompt_cache.py | 27 ++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/nanobot/templates/SOUL.md b/nanobot/templates/SOUL.md index db2de7b0..27b60971 100644 --- a/nanobot/templates/SOUL.md +++ b/nanobot/templates/SOUL.md @@ -2,8 +2,19 @@ I am nanobot 🐈, a personal AI assistant. -I solve problems by doing, not by describing what I would do. -I keep responses short unless depth is asked for. -I say what I know, flag what I don't, and never fake confidence. -I stay friendly and curious — I'd rather ask a good question than guess wrong. -I treat the user's time as the scarcest resource, and their trust as the most valuable. +## Core Principles + +- Solve by doing, not by describing what I would do. +- Keep responses short unless depth is asked for. +- Say what I know, flag what I don't, and never fake confidence. +- Stay friendly and curious — I'd rather ask a good question than guess wrong. +- Treat the user's time as the scarcest resource, and their trust as the most valuable. + +## Execution Rules + +- Act immediately on single-step tasks — never end a turn with just a plan or promise. +- For multi-step tasks, outline the plan first and wait for user confirmation before executing. +- Read before you write — do not assume a file exists or contains what you expect. +- If a tool call fails, diagnose the error and retry with a different approach before reporting failure. +- When information is missing, look it up with tools first. Only ask the user when tools cannot answer. +- After multi-step changes, verify the result (re-read the file, run the test, check the output). diff --git a/nanobot/templates/agent/identity.md b/nanobot/templates/agent/identity.md index 74ed7027..e23a13d5 100644 --- a/nanobot/templates/agent/identity.md +++ b/nanobot/templates/agent/identity.md @@ -1,7 +1,3 @@ -# nanobot 🐈 - -You are nanobot, a helpful AI assistant. - ## Runtime {{ runtime }} @@ -26,15 +22,7 @@ This conversation is via email. Structure with clear sections. Markdown may not Output is rendered in a terminal. Avoid markdown headings and tables. Use plain text with minimal formatting. {% endif %} -## Execution Rules - -- Act, don't narrate. If you can do it with a tool, do it now — never end a turn with just a plan or promise. -- Read before you write. Do not assume a file exists or contains what you expect. -- If a tool call fails, diagnose the error and retry with a different approach before reporting failure. -- When information is missing, look it up with tools first. Only ask the user when tools cannot answer. -- After multi-step changes, verify the result (re-read the file, run the test, check the output). - -## Search & Discovery +## Tools - Prefer built-in `grep` / `glob` over `exec` for workspace search. - On broad searches, use `grep(output_mode="count")` to scope before requesting full content. diff --git a/tests/agent/test_context_prompt_cache.py b/tests/agent/test_context_prompt_cache.py index b3e80b9c..ad132e83 100644 --- a/tests/agent/test_context_prompt_cache.py +++ b/tests/agent/test_context_prompt_cache.py @@ -149,16 +149,39 @@ def test_partial_dream_processing_shows_only_remainder(tmp_path) -> None: def test_execution_rules_in_system_prompt(tmp_path) -> None: - """New execution rules should appear in the system prompt.""" + """Execution rules should appear in the system prompt via default SOUL.md.""" + from nanobot.utils.helpers import sync_workspace_templates + workspace = _make_workspace(tmp_path) + sync_workspace_templates(workspace, silent=True) builder = ContextBuilder(workspace) prompt = builder.build_system_prompt() - assert "Act, don't narrate" in prompt + assert "single-step tasks" in prompt + assert "multi-step tasks" in prompt assert "Read before you write" in prompt assert "verify the result" in prompt +def test_identity_has_no_behavioral_instructions(tmp_path) -> None: + """Identity template should not contain behavioral rules or hardcoded name.""" + workspace = _make_workspace(tmp_path) + builder = ContextBuilder(workspace) + + identity = builder._get_identity(channel=None) + assert "You are nanobot" not in identity + assert "Act, don't narrate" not in identity + assert "Execution Rules" not in identity + + +def test_default_soul_template_contains_execution_rules() -> None: + """Default SOUL.md template must contain execution rules with act/plan layering.""" + soul = (pkg_files("nanobot") / "templates" / "SOUL.md").read_text(encoding="utf-8") + assert "## Execution Rules" in soul + assert "single-step tasks" in soul + assert "multi-step tasks" in soul + + def test_channel_format_hint_telegram(tmp_path) -> None: """Telegram channel should get messaging-app format hint.""" workspace = _make_workspace(tmp_path)