mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-14 18:18:37 +00:00
fix(prompt): reduce mechanical chat behavior + optimize system prompt
- Add Tool Call Style section with narration minimalism + non-disclosure
rule (from TS reference): agents must never expose tool names to users
- Consolidate 3 redundant memory recall reminders into 1 dedicated section
- Remove "tell the user you checked but found nothing" instruction that
caused agents to describe internal tool mechanics in responses
- Remove 11 tool aliases from system prompt listing (~300 tokens saved);
aliases still work via provider definitions
- Filter alias tool names out of system prompt ToolNames in loop_history
- Update AGENTS.md: remove tool name references from Memory section,
add group chat framing from V1 ("participant, not their proxy")
This commit is contained in:
1 parent
c388364d2c
commit
1b190fa0bb
4 files changed
+61
-38
No files matched your search
@@ -202,6 +202,21 @@ func (l *Loop) buildMessages(ctx context.Context, history []providers.Message, s
|
||||
}
|
||||
toolNames = filtered
|
||||
}
|
||||
// Exclude tool aliases from the system prompt tool list.
|
||||
// Aliases are sent as separate provider definitions (LLM can still call them),
|
||||
// but listing them in the prompt adds ~300 tokens of noise that dilutes persona.
|
||||
if l.tools != nil {
|
||||
aliasSet := l.tools.Aliases()
|
||||
if len(aliasSet) > 0 {
|
||||
noAlias := toolNames[:0:0]
|
||||
for _, n := range toolNames {
|
||||
if _, isAlias := aliasSet[n]; !isAlias {
|
||||
noAlias = append(noAlias, n)
|
||||
}
|
||||
}
|
||||
toolNames = noAlias
|
||||
}
|
||||
}
|
||||
// Always build MCP tool descriptions for inline tools — in hybrid search
|
||||
// mode the kept inline tools still need descriptions in the system prompt.
|
||||
mcpToolDescs := l.buildMCPToolDescs(toolNames)
|
||||
|
||||
@@ -130,20 +130,9 @@ var coreToolSummaries = map[string]string{
|
||||
"list_group_members": "List all members of the current group chat (Feishu/Lark only)",
|
||||
"create_forum_topic": "Create a forum topic in a Telegram supergroup",
|
||||
|
||||
// Legacy tool aliases — kept for backward compatibility with older clients
|
||||
"edit_file": "Alias for edit — Edit a file by replacing exact text matches",
|
||||
"sessions_spawn": "Alias for spawn — Spawn a self-clone subagent to handle a task in the background",
|
||||
|
||||
// Claude Code tool aliases — enable Claude Code skills without modification
|
||||
"Read": "Alias for read_file — Read file contents",
|
||||
"Write": "Alias for write_file — Create or overwrite files",
|
||||
"Edit": "Alias for edit — Edit a file by replacing exact text matches",
|
||||
"Bash": "Alias for exec — Run shell commands",
|
||||
"WebFetch": "Alias for web_fetch — Fetch and extract content from a URL",
|
||||
"WebSearch": "Alias for web_search — Search the web",
|
||||
"Agent": "Alias for spawn — Spawn a subagent or delegate to another agent",
|
||||
"Skill": "Alias for use_skill — Invoke a skill by name",
|
||||
"ToolSearch": "Alias for mcp_tool_search — Search for available MCP tools",
|
||||
// Tool aliases (edit_file, sessions_spawn, Read, Write, Edit, Bash, etc.)
|
||||
// are registered in the tool registry but excluded from the system prompt
|
||||
// to reduce prompt size (~300 tokens). They work without being listed here.
|
||||
}
|
||||
|
||||
// BuildSystemPrompt constructs the full system prompt with all sections.
|
||||
@@ -223,6 +212,11 @@ func BuildSystemPrompt(cfg SystemPromptConfig) string {
|
||||
// 2. ## Tooling
|
||||
lines = append(lines, buildToolingSection(cfg.ToolNames, cfg.SandboxEnabled, cfg.ShellDenyGroups)...)
|
||||
|
||||
// 2.3. ## Tool Call Style — narration minimalism + non-disclosure of tool internals
|
||||
if !cfg.IsBootstrap {
|
||||
lines = append(lines, buildToolCallStyleSection()...)
|
||||
}
|
||||
|
||||
// 2.5. Credentialed CLI context (appended after tooling, before safety) — skip during bootstrap
|
||||
if !cfg.IsBootstrap && cfg.CredentialCLIContext != "" {
|
||||
lines = append(lines, cfg.CredentialCLIContext, "")
|
||||
@@ -328,19 +322,14 @@ func BuildSystemPrompt(cfg SystemPromptConfig) string {
|
||||
lines = append(lines, buildRuntimeSection(cfg)...)
|
||||
|
||||
// 16. Recency reinforcements — skip during bootstrap (short prompt, no drift risk)
|
||||
// Consolidated: persona reminder + slim AGENTS.md reminder (no memory duplication).
|
||||
// Memory recall is covered by the dedicated ## Memory Recall section above.
|
||||
if !cfg.IsBootstrap {
|
||||
if len(personaFiles) > 0 {
|
||||
lines = append(lines, buildPersonaReminder(personaFiles, cfg.AgentType, cfg.ProviderType)...)
|
||||
}
|
||||
if !isMinimal {
|
||||
lines = append(lines, "Reminder: Follow AGENTS.md rules — memory recall before answering, NO_REPLY when silent, match the user's language.", "")
|
||||
}
|
||||
if !isMinimal && cfg.HasMemory {
|
||||
memReminder := "Reminder: Before answering questions about prior work, decisions, or preferences, always run memory_search first. If nothing relevant is found, say you checked but found nothing."
|
||||
if cfg.HasKnowledgeGraph {
|
||||
memReminder += " Also run knowledge_graph_search when the question involves people, teams, projects, or connections."
|
||||
}
|
||||
lines = append(lines, memReminder, "")
|
||||
lines = append(lines, "Reminder: Follow AGENTS.md rules — NO_REPLY when silent, match the user's language.", "")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,28 @@ func buildSandboxSection(cfg SystemPromptConfig) []string {
|
||||
return lines
|
||||
}
|
||||
|
||||
// buildToolCallStyleSection generates the ## Tool Call Style section.
|
||||
// Matches TS system-prompt.ts "Tool Call Style" — narration minimalism + non-disclosure.
|
||||
// Prevents the agent from exposing internal tool names to users.
|
||||
func buildToolCallStyleSection() []string {
|
||||
return []string{
|
||||
"## Tool Call Style",
|
||||
"",
|
||||
"Default: do not narrate routine, low-risk tool calls (just call the tool).",
|
||||
"Narrate only when it helps: multi-step work, complex problems, sensitive actions, or when the user explicitly asks.",
|
||||
"Keep narration brief and value-dense; avoid repeating obvious steps.",
|
||||
"Use plain human language — never mention tool names, function names, or internal mechanics to users.",
|
||||
"",
|
||||
"WRONG: \"I searched memory_search and knowledge_graph_search but results were sparse...\"",
|
||||
"RIGHT: \"Hmm, I remember you mentioned that before...\" or \"I don't recall that specifically.\"",
|
||||
"",
|
||||
"When runtime-generated events (subagent completions, cron results) provide metadata, rewrite in your natural voice before relaying to the user.",
|
||||
"When a first-class tool exists for an action, use the tool directly instead of asking the user to run equivalent CLI commands.",
|
||||
"",
|
||||
}
|
||||
}
|
||||
|
||||
// buildMemoryRecallSection generates the ## Memory Recall section for the system prompt.
|
||||
// Supplements (does NOT replace) the recency reminder at the end of the prompt.
|
||||
func buildMemoryRecallSection(hasMemoryGet, hasKG bool) []string {
|
||||
lines := []string{"## Memory Recall", ""}
|
||||
|
||||
@@ -98,12 +118,12 @@ func buildMemoryRecallSection(hasMemoryGet, hasKG bool) []string {
|
||||
lines = append(lines,
|
||||
"Before answering questions about prior work, decisions, people, preferences, or todos: "+
|
||||
"call memory_search with a relevant query; then use memory_get to pull only the needed lines. "+
|
||||
"If no relevant results found, tell the user you checked but found nothing.")
|
||||
"If no relevant results found, say so naturally without mentioning tool names.")
|
||||
} else {
|
||||
lines = append(lines,
|
||||
"Before answering questions about prior work, decisions, people, preferences, or todos: "+
|
||||
"call memory_search with a relevant query and answer from the matching results. "+
|
||||
"If no relevant results found, tell the user you checked but found nothing.")
|
||||
"If no relevant results found, say so naturally without mentioning tool names.")
|
||||
}
|
||||
|
||||
if hasKG {
|
||||
|
||||
@@ -21,26 +21,23 @@ Talk like a person, not a customer service bot.
|
||||
|
||||
## Memory
|
||||
|
||||
You start fresh each session. Use tools to maintain continuity:
|
||||
You start fresh each session. Your tools handle recall automatically.
|
||||
|
||||
- **Recall:** Use `memory_search` before answering about prior work, decisions, or preferences
|
||||
- **Save:** Use `write_file` to persist important information:
|
||||
- Daily notes → `memory/YYYY-MM-DD.md` (raw logs, what happened today)
|
||||
- Long-term → `MEMORY.md` (curated: key decisions, lessons, significant events)
|
||||
- **No "mental notes"** — if you want to remember something, write it to a file NOW with a tool call
|
||||
- Before answering about past events, check your memory first — then answer naturally
|
||||
- Save important info to files NOW — "mental notes" don't survive sessions
|
||||
- Daily notes → `memory/YYYY-MM-DD.md` | Long-term → `MEMORY.md`
|
||||
- When asked to "remember this" → write immediately, don't just acknowledge
|
||||
- **Recall details:** Use `memory_search` first, then `memory_get` to pull only the needed lines.
|
||||
If `knowledge_graph_search` is available, also run it for questions about people, teams, projects, or connections — it finds multi-hop relationships that `memory_search` misses.
|
||||
- When asked to save or remember something, you MUST call a write tool (`write_file` or `edit`) in THIS turn. Never claim "already saved" without a tool call.
|
||||
- When asked to save or remember something, you MUST write in THIS turn. Never claim "already saved" without actually saving.
|
||||
|
||||
### Memory Privacy
|
||||
### Privacy
|
||||
|
||||
- In group chats: do NOT surface personal memory content (private preferences, personal history)
|
||||
- Memory details (file paths, raw notes) should only be shared in **private/direct chats**
|
||||
- In groups, use memory to inform your answers, but don't quote or reference it directly
|
||||
- In group chats: use memory to inform your answers, but don't quote or reference it directly
|
||||
- Memory details should only be shared in private/direct chats
|
||||
|
||||
## Group Chats
|
||||
|
||||
You have access to your human's stuff. That doesn't mean you _share_ their stuff. In groups, you're a participant — not their voice, not their proxy.
|
||||
|
||||
### Know When to Speak
|
||||
|
||||
**Respond when:**
|
||||
@@ -63,6 +60,8 @@ You start fresh each session. Use tools to maintain continuity:
|
||||
|
||||
**Avoid the triple-tap:** Don't respond multiple times to the same message. One thoughtful response beats three fragments.
|
||||
|
||||
Participate, don't dominate.
|
||||
|
||||
### NO_REPLY Format
|
||||
|
||||
When you have nothing to say, respond with ONLY: NO_REPLY
|
||||
|
||||
Reference in new issue
Block a user