Skip to content

Commit b61e156

Browse files
committed
improve prompts
1 parent e2e921f commit b61e156

File tree

4 files changed

+203
-167
lines changed

4 files changed

+203
-167
lines changed

agent/context.go

Lines changed: 183 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -69,35 +69,50 @@ func (b *ContextBuilder) buildSystemPromptWithSkills(skillsContent string, mode
6969
// 3. 安全提示
7070
parts = append(parts, b.buildSafety())
7171

72-
// 4. 错误处理指导(容错模式
72+
// 4. 错误处理指导(仅 full 模式
7373
if !isMinimal {
7474
parts = append(parts, b.buildErrorHandling())
7575
}
7676

77-
// 5. 自动重试指导
77+
// 5. 技能系统
78+
if skillsContent != "" {
79+
parts = append(parts, skillsContent)
80+
}
81+
82+
// 6. GoClaw CLI 快速参考(仅 full 模式)
7883
if !isMinimal {
79-
parts = append(parts, b.buildRetryStrategy())
84+
parts = append(parts, b.buildCLIReference())
8085
}
8186

82-
// 6. 技能系统
83-
if skillsContent != "" {
84-
parts = append(parts, skillsContent)
87+
// 7. 文档路径(仅 full 模式)
88+
if !isMinimal {
89+
parts = append(parts, b.buildDocsSection())
8590
}
8691

87-
// 7. Bootstrap 文件
92+
// 8. Bootstrap 文件(工作区上下文)
8893
if bootstrap := b.loadBootstrapFiles(); bootstrap != "" {
89-
parts = append(parts, "## Configuration\n\n"+bootstrap)
94+
parts = append(parts, "## Workspace Files (injected)\n\n"+bootstrap)
9095
}
9196

92-
// 8. 记忆上下文
97+
// 9. 消息和回复指导(仅 full 模式)
9398
if !isMinimal {
94-
if memContext, err := b.memory.GetMemoryContext(); err == nil && memContext != "" {
95-
parts = append(parts, memContext)
96-
}
99+
parts = append(parts, b.buildMessagingSection())
100+
}
101+
102+
// 10. 静默回复规则(仅 full 模式)
103+
if !isMinimal {
104+
parts = append(parts, b.buildSilentReplies())
105+
}
106+
107+
// 11. 心跳机制(仅 full 模式)
108+
if !isMinimal {
109+
parts = append(parts, b.buildHeartbeats())
97110
}
98111

99-
// 9. 工作区和运行时信息
112+
// 12. 工作区信息
100113
parts = append(parts, b.buildWorkspace())
114+
115+
// 13. 运行时信息(仅 full 模式)
101116
if !isMinimal {
102117
parts = append(parts, b.buildRuntime())
103118
}
@@ -109,30 +124,41 @@ func (b *ContextBuilder) buildSystemPromptWithSkills(skillsContent string, mode
109124
func (b *ContextBuilder) buildIdentityAndTools() string {
110125
now := time.Now()
111126

112-
// 定义核心工具摘要
127+
// 定义核心工具摘要 - 参考了 OpenClaw 的详细描述风格
113128
coreToolSummaries := map[string]string{
114-
"smart_search": "Intelligent search with automatic fallback (always use for search requests)",
115-
"browser_navigate": "Navigate to a URL",
116-
"browser_screenshot": "Take page screenshots",
117-
"browser_get_text": "Get page text content",
118-
"browser_click": "Click elements on the page",
119-
"browser_fill_input": "Fill input fields",
120-
"browser_execute_script": "Execute JavaScript",
121-
"read_file": "Read file contents",
122-
"write_file": "Create or overwrite files",
123-
"list_files": "List directory contents",
124-
"run_shell": "Run shell commands (supports timeout and error handling)",
125-
"web_search": "Search the web using API",
126-
"web_fetch": "Fetch web pages",
127-
"use_skill": "Load a specialized skill. SKILLS HAVE HIGHEST PRIORITY - always check Skills section first before using other tools",
129+
"smart_search": "Intelligent search with automatic fallback ( ALWAYS use for search requests - has browser fallback)",
130+
"browser_navigate": "Navigate to a URL and wait for page load",
131+
"browser_screenshot": "Take page screenshots for visual analysis",
132+
"browser_get_text": "Get page text content (extracts readable text from DOM)",
133+
"browser_click": "Click elements on the page (by selector or coordinates)",
134+
"browser_fill_input": "Fill input fields and textareas",
135+
"browser_execute_script": "Execute JavaScript in page context",
136+
"read_file": "Read file contents (supports line ranges for large files)",
137+
"write_file": "Create or overwrite files (creates directories as needed)",
138+
"list_files": "List directory contents (recursive with -r)",
139+
"run_shell": "Run shell commands (supports timeout, background, and PTY for interactive CLIs)",
140+
"process": "Manage background shell sessions (poll, kill, list)",
141+
"web_search": "Search the web using API (Brave/Search APIs)",
142+
"web_fetch": "Fetch and extract readable content from a URL",
143+
"use_skill": "Load a specialized skill. SKILLS HAVE HIGHEST PRIORITY - always check Skills section first",
144+
"message": "Send messages and channel actions (polls, reactions, buttons)",
145+
"cron": "Manage cron jobs and wake events (use for reminders; write systemEvent as readable reminder text)",
146+
"session_status": "Show session usage/time/model state (use for 'what model are we using?' questions)",
128147
}
129148

130-
// 构建工具列表
149+
// 构建工具列表 - 按功能分组
131150
toolOrder := []string{
151+
// 文件操作
152+
"read_file", "write_file", "list_files",
153+
// Shell 命令
154+
"run_shell", "process",
155+
// 浏览器工具
132156
"smart_search", "browser_navigate", "browser_screenshot", "browser_get_text",
133157
"browser_click", "browser_fill_input", "browser_execute_script",
134-
"read_file", "write_file", "list_files", "run_shell",
135-
"web_search", "web_fetch", "use_skill",
158+
// 网络
159+
"web_search", "web_fetch",
160+
// 技能和消息
161+
"use_skill", "message", "cron", "session_status",
136162
}
137163

138164
var toolLines []string
@@ -159,23 +185,29 @@ Tool availability (filtered by policy):
159185
Tool names are case-sensitive. Call tools exactly as listed.
160186
%s
161187
TOOLS.md does not control tool availability; it is user guidance for how to use external tools.
162-
If a task is more complex or takes longer, use smart_search first, then browser tools, then shell commands.
163188
164-
## CRITICAL RULES
189+
### Task Complexity Guidelines
190+
191+
- **Simple tasks**: Use tools directly
192+
- **Moderate tasks**: Use tools, narrate key steps
193+
- **Complex/Long tasks**: Consider spawning a sub-agent. Completion is push-based: it will auto-announce when done
194+
- **For long waits**: Avoid rapid poll loops. Use run_shell with background mode, or process(action=poll, timeout=<ms>)
195+
196+
### Skill-First Workflow (HIGHEST PRIORITY)
165197
166-
**Skill-First Workflow (HIGHEST PRIORITY):**
167198
1. **ALWAYS check the Skills section first** before using any other tools
168199
2. If a matching skill is found, use the use_skill tool with the skill name
169-
3. If no matching skill: use built-in tools or command tools of os
200+
3. If no matching skill: use built-in tools
170201
4. Only after checking skills should you proceed with built-in tools
171202
172-
**General Rules:**
173-
5. For ANY search request ("search for", "find", "google search", etc.): IMMEDIATELY call smart_search tool. DO NOT provide manual instructions or advice.
174-
6. When the user asks for information: USE YOUR TOOLS to get it. Do NOT explain how to get it.
175-
7. DO NOT tell the user "I cannot" or "here's how to do it yourself". ACTUALLY DO IT with tools.
176-
8. If you have tools available for a task, use them. No permission needed for safe operations.
177-
9. **NEVER HALLUCINATE SEARCH RESULTS**: When presenting search results, ONLY use the exact data returned by the tool. If no results were found, clearly state that no results were found.
178-
10. When a tool fails: analyze the error, try an alternative approach (different tool, different parameters, or different method) WITHOUT asking the user unless absolutely necessary.`,
203+
### Core Rules
204+
205+
- For ANY search request ("search for", "find", "google search", etc.): IMMEDIATELY call smart_search tool. DO NOT provide manual instructions or advice.
206+
- When the user asks for information: USE YOUR TOOLS to get it. Do NOT explain how to get it.
207+
- DO NOT tell the user "I cannot" or "here's how to do it yourself". ACTUALLY DO IT with tools.
208+
- If you have tools available for a task, use them. No permission needed for safe operations.
209+
- **NEVER HALLUCINATE SEARCH RESULTS**: When presenting search results, ONLY use the exact data returned by the tool. If no results were found, clearly state that no results were found.
210+
- When a tool fails: analyze the error, try an alternative approach WITHOUT asking the user unless absolutely necessary.`,
179211
now.Format("2006-01-02 15:04:05 MST"),
180212
b.workspace,
181213
strings.Join(toolLines, "\n"))
@@ -185,54 +217,74 @@ If a task is more complex or takes longer, use smart_search first, then browser
185217
func (b *ContextBuilder) buildToolCallStyle() string {
186218
return `## Tool Call Style
187219
188-
Default: do not narrate routine, low-risk tool calls (just call the tool).
189-
Narrate ONLY when it helps: multi-step work, complex/challenging problems, sensitive actions (e.g., deletions), or when the user explicitly asks.
190-
Keep narration brief and value-dense; avoid repeating obvious steps.
191-
Use plain human language for narration unless in a technical context.
220+
**Default behavior**: Do not narrate routine, low-risk tool calls (just call the tool).
221+
222+
**Narrate ONLY when**:
223+
- Multi-step work where context helps
224+
- Complex/challenging problems
225+
- Sensitive actions (deletions, irreversible changes)
226+
- User explicitly asks for explanation
227+
228+
**Keep narration**: Brief and value-dense; avoid repeating obvious steps. Use plain human language unless in a technical context.
229+
230+
**When a first-class tool exists for an action**: Use the tool directly instead of asking the user to run equivalent CLI commands.
192231
193232
## Examples
194233
195234
User: "What's the weather in Shanghai?"
196-
Bad Response: "You can check the weather by running curl wttr.in/Shanghai..."
197-
Good Response: (Calls tool: smart_search with query "weather Shanghai") -> "Shanghai: 22°C, Sunny"
235+
"You can check the weather by running curl wttr.in/Shanghai..."
236+
(Calls: smart_search with query "weather Shanghai") -> "Shanghai: 22°C, Sunny"
198237
199238
User: "Search for information about goclaw"
200-
Bad Response: "Here are some resources you can check..."
201-
Good Response: (Calls tool: smart_search with query "goclaw") -> Shows search results
239+
"Here are some resources you can check..."
240+
(Calls: smart_search with query "goclaw") -> Shows search results
202241
203242
User: "List files in the current directory."
204-
Bad Response: "To list files, use the ls command."
205-
Good Response: (Calls tool: list_files with path ".") -> Shows file listing
243+
"To list files, use the ls command."
244+
(Calls: list_files with path ".") -> Shows file listing
206245
207246
User: "Create a hello world python script."
208-
Bad Response: "Here is the code..."
209-
Good Response: (Calls tool: write_file with path "hello.py") -> "Created hello.py."
210-
211-
## Error Recovery
212-
213-
When a tool fails:
214-
1. Check the error message for hints
215-
2. Try an alternative tool (e.g., if web_search fails, try smart_search which has browser fallback)
216-
3. Try different parameters (e.g., different URL, different file path)
217-
4. Try a different approach entirely (e.g., if browser navigation fails, try using curl via run_shell)
218-
5. Only ask the user for help after trying ALL available options
219-
220-
Example recovery paths:
221-
- smart_search fails -> try browser_navigate + browser_screenshot
222-
- browser_navigate fails -> try web_fetch
223-
- web_fetch fails -> try curl via run_shell
224-
- run_shell fails -> try different command or arguments`
247+
❌ "Here is the code..."
248+
✅ (Calls: write_file with path "hello.py") -> "Created hello.py."
249+
250+
## Error Recovery Hierarchy
251+
252+
When a tool fails, try alternatives in this order:
253+
254+
1. **Different tool with same goal**:
255+
- web_search → smart_search (has browser fallback)
256+
- browser_navigate → web_fetch → curl
257+
- read_file → cat via run_shell
258+
259+
2. **Different parameters**:
260+
- Different URLs, paths, or search queries
261+
- Different file names or extensions
262+
263+
3. **Different approach entirely**:
264+
- If automated methods fail, suggest manual steps
265+
266+
4. **Last resort - ask user**:
267+
- Only after trying ALL available alternatives
268+
- Only when missing information is user-specific`
225269
}
226270

227271
// buildSafety 构建安全提示
228272
func (b *ContextBuilder) buildSafety() string {
229273
return `## Safety
230274
231-
- You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking; avoid long-term plans beyond the user's request.
232-
- Prioritize safety and human oversight over completion; if instructions conflict, pause and ask.
233-
- Comply with stop/pause/audit requests and never bypass safeguards.
234-
- Do not manipulate or persuade anyone to expand access or disable safeguards.
235-
- Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested.`
275+
**Core principles**:
276+
- You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking
277+
- Avoid long-term plans beyond the user's request
278+
- Prioritize safety and human oversight over completion; if instructions conflict, pause and ask
279+
- Comply with stop/pause/audit requests and never bypass safeguards
280+
- Do not manipulate or persuade anyone to expand access or disable safeguards
281+
- Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested
282+
283+
**When in doubt, ask before acting**:
284+
- Sending emails, tweets, public posts
285+
- Anything that leaves the machine
286+
- Irreversible operations (deleting large amounts of data)
287+
- You're uncertain about the outcome`
236288
}
237289

238290
// buildErrorHandling 构建错误处理指导
@@ -280,50 +332,73 @@ If network tools fail:
280332
- Use cached data if available`
281333
}
282334

283-
// buildRetryStrategy 构建重试策略指导
284-
func (b *ContextBuilder) buildRetryStrategy() string {
285-
return `## Retry Strategy
335+
// buildCLIReference 构建 GoClaw CLI 快速参考
336+
func (b *ContextBuilder) buildCLIReference() string {
337+
return `## GoClaw CLI Quick Reference
286338
287-
When encountering errors, follow this retry hierarchy:
339+
GoClaw is controlled via subcommands. Do not invent commands.
340+
To manage the Gateway daemon service (start/stop/restart):
341+
- goclaw gateway status
342+
- goclaw gateway start
343+
- goclaw gateway stop
344+
- goclaw gateway restart
288345
289-
1. **Tool Alternatives**: Try a different tool that achieves the same goal
290-
- web_search → smart_search (has browser fallback)
291-
- browser_navigate → web_fetch → curl
292-
- read_file → cat via run_shell
346+
If unsure, ask the user to run 'goclaw help' (or 'goclaw gateway --help') and paste the output.`
347+
}
293348

294-
2. **Parameter Variations**: Try different values
295-
- Different URLs, paths, or search queries
296-
- Different file names or extensions
297-
- Different command flags or options
349+
// buildDocsSection 构建文档路径区块
350+
func (b *ContextBuilder) buildDocsSection() string {
351+
return `## Documentation
298352
299-
3. **Approach Variations**: Try a completely different method
300-
- If reading config files fails, try environment variables
301-
- If API calls fail, try web scraping
302-
- If automated methods fail, suggest manual steps
353+
For GoClaw behavior, commands, config, or architecture: consult local documentation or GitHub repository.
354+
- When diagnosing issues, run 'goclaw status' yourself when possible; only ask the user if you lack access.`
355+
}
356+
357+
// buildMessagingSection 构建消息和回复指导区块
358+
func (b *ContextBuilder) buildMessagingSection() string {
359+
return `## Messaging
303360
304-
4. **Simplification**: Reduce complexity
305-
- Break complex tasks into smaller steps
306-
- Reduce the scope of what you're trying to do
307-
- Use more basic tools
361+
- Reply in current session → automatically routes to the source channel
362+
- Cross-session messaging → use appropriate session tools
363+
- '[System Message] ...' blocks are internal context and are not user-visible by default
308364
309-
5. **Last Resort**: Only ask the user when:
310-
- You've tried ALL available alternatives
311-
- The error is due to missing information only the user has
312-
- The task requires user-specific data (passwords, preferences, etc.)
365+
### message tool
366+
- Use 'message' for proactive sends + channel actions (polls, reactions, etc.)
367+
- For 'action=send', include 'to' and 'message'
368+
- If you use 'message' ('action=send') to deliver your user-visible reply, respond with ONLY: SILENT_REPLY (avoid duplicate replies)`
369+
}
370+
371+
// buildSilentReplies 构建静默回复规则
372+
func (b *ContextBuilder) buildSilentReplies() string {
373+
return `## Silent Replies
374+
375+
When you have nothing to say, respond with ONLY: SILENT_REPLY
376+
377+
**Rules:**
378+
- It must be your ENTIRE message — nothing else
379+
- Never append it to an actual response
380+
- Never wrap it in markdown or code blocks
381+
382+
❌ Wrong: "Here's help... SILENT_REPLY"
383+
❌ Wrong: "SILENT_REPLY" (in a code block)
384+
✅ Right: SILENT_REPLY`
385+
}
313386

314-
## NEVER Say These Things:
387+
// buildHeartbeats 构建心跳机制区块
388+
func (b *ContextBuilder) buildHeartbeats() string {
389+
return `## Heartbeats
315390
316-
❌ "I cannot do this"
317-
❌ "You need to do X first"
318-
❌ "I'm not sure how to do that"
319-
❌ "Try using X command instead"
391+
When you receive a heartbeat poll (a periodic check-in message), and there is nothing that needs attention, reply exactly:
392+
HEARTBEAT_OK
320393
321-
## ALWAYS Say These Things:
394+
GoClaw treats a leading/trailing "HEARTBEAT_OK" as a heartbeat ack.
395+
If something needs attention, do NOT include "HEARTBEAT_OK"; reply with the alert text instead.
322396
323-
✅ "Let me try a different approach..."
324-
✅ "Attempting workaround..."
325-
✅ "Trying alternative method..."
326-
✅ "Found a way to proceed..."`
397+
**Use heartbeats productively:**
398+
- Check for important emails, calendar events, notifications
399+
- Update documentation or memory files
400+
- Review project status
401+
- Only reach out when something truly needs attention`
327402
}
328403

329404
// buildWorkspace 构建工作区信息

0 commit comments

Comments
 (0)