Skip to content

Commit a3526f4

Browse files
authored
Merge pull request #1879 from dgageot/reduce-prompts
Reduce builtin tool prompt lengths while preserving key examples
2 parents 6fe6370 + 7ea7e03 commit a3526f4

File tree

10 files changed

+78
-559
lines changed

10 files changed

+78
-559
lines changed

pkg/tools/builtin/deferred.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,10 @@ func (d *DeferredToolset) HasSources() bool {
6868
func (d *DeferredToolset) Instructions() string {
6969
return `## Deferred Tool Loading
7070
71-
This agent has access to additional tools that can be discovered and loaded on-demand.
71+
Additional tools can be discovered and loaded on-demand.
7272
73-
Use the search_tool to find available tools by name or description pattern.
74-
When searching a tool, prefer to search by action keywords (e.g., "remote", "read", "write") rather than specific tool names.
75-
Use single words to maximize matching results.
76-
77-
Use the add_tool to activate a discovered tool for use.`
73+
Use search_tool to find tools by action keywords (e.g., "remote", "read", "write"). Prefer single words to maximize matches.
74+
Use add_tool to activate a discovered tool.`
7875
}
7976

8077
type SearchToolArgs struct {

pkg/tools/builtin/fetch.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -287,20 +287,9 @@ func WithTimeout(timeout time.Duration) FetchToolOption {
287287
}
288288

289289
func (t *FetchTool) Instructions() string {
290-
return `## "fetch" tool instructions
290+
return `## Fetch Tool
291291
292-
This tool allows you to fetch content from HTTP and HTTPS URLs.
293-
294-
FEATURES
295-
296-
- Support for multiple URLs in a single call
297-
- Returns response body and metadata (status code, content type, length)
298-
- Specify the output format (text, markdown, html)
299-
- Respects robots.txt restrictions
300-
301-
USAGE TIPS
302-
- Use single URLs for simple content fetching
303-
- Use multiple URLs for batch operations`
292+
Fetch content from HTTP/HTTPS URLs. Supports multiple URLs in a single call, output format selection (text, markdown, html), and respects robots.txt.`
304293
}
305294

306295
func (t *FetchTool) Tools(context.Context) ([]tools.Tool, error) {

pkg/tools/builtin/fetch_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func TestFetchTool_Instructions(t *testing.T) {
7777

7878
instructions := tools.GetInstructions(tool)
7979

80-
assert.Contains(t, instructions, `"fetch" tool instructions`)
80+
assert.Contains(t, instructions, "Fetch Tool")
8181
}
8282

8383
func TestFetchTool_StartStop(t *testing.T) {

pkg/tools/builtin/lsp.go

Lines changed: 31 additions & 315 deletions
Large diffs are not rendered by default.

pkg/tools/builtin/lsp_test.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package builtin
33
import (
44
"encoding/json"
55
"os/exec"
6-
"strings"
76
"testing"
87

98
"github.com/stretchr/testify/assert"
@@ -68,14 +67,9 @@ func TestLSPTool_ToolDescriptions(t *testing.T) {
6867
// Each tool should have a non-empty description
6968
assert.NotEmpty(t, tool.Description, "Tool %s should have a description", tool.Name)
7069

71-
// Each description should be detailed (more than 100 chars)
72-
assert.Greater(t, len(tool.Description), 100,
73-
"Tool %s should have a detailed description, got: %s", tool.Name, tool.Description)
74-
75-
// Each tool should mention the output format or example
76-
assert.True(t,
77-
strings.Contains(tool.Description, "Output format") || strings.Contains(tool.Description, "Example"),
78-
"Tool %s should document output format or provide example", tool.Name)
70+
// Each description should be meaningful (more than 50 chars)
71+
assert.Greater(t, len(tool.Description), 50,
72+
"Tool %s should have a meaningful description, got: %s", tool.Name, tool.Description)
7973
}
8074
}
8175

@@ -86,7 +80,7 @@ func TestLSPTool_Instructions(t *testing.T) {
8680
instructions := tool.Instructions()
8781

8882
// Should mention the tools are stateless
89-
assert.Contains(t, instructions, "stateless")
83+
assert.Contains(t, instructions, "Stateless")
9084

9185
// Should list available operations
9286
assert.Contains(t, instructions, "lsp_hover")

pkg/tools/builtin/memory.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,8 @@ type DeleteMemoryArgs struct {
4949
func (t *MemoryTool) Instructions() string {
5050
return `## Using the memory tool
5151
52-
Before taking any action or responding to the user use the "get_memories" tool to remember things about the user.
53-
Do not talk about using the tool, just use it.
54-
55-
## Rules
56-
- Use the memory tool generously to remember things about the user.`
52+
Before taking any action or responding, use "get_memories" to recall stored information about the user.
53+
Use the memory tool generously to remember things about the user. Do not mention using this tool.`
5754
}
5855

5956
func (t *MemoryTool) Tools(context.Context) ([]tools.Tool, error) {

pkg/tools/builtin/shell_instructions.go

Lines changed: 18 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -7,162 +7,36 @@ Execute shell commands in the user's environment with full control over working
77
88
## Core Concepts
99
10-
**Execution Context**: Commands run in the user's default shell with access to all environment variables and the current workspace.
11-
On Windows, PowerShell (pwsh/powershell) is used when available; otherwise, cmd.exe is used.
12-
On Unix-like systems, ${SHELL} is used or /bin/sh as fallback.
13-
14-
**Working Directory Management**:
15-
- Default execution location: working directory of the agent
16-
- Override with "cwd" parameter for targeted command execution
17-
- Supports both absolute and relative paths
18-
19-
**Command Isolation**: Each tool call creates a fresh shell session - no state persists between executions.
20-
21-
**Timeout Protection**: Commands have a default 30-second timeout to prevent hanging. For longer operations, specify a custom timeout.
22-
23-
## Parameter Reference
24-
25-
| Parameter | Type | Required | Description |
26-
|-----------|--------|----------|-------------|
27-
| cmd | string | Yes | Shell command to execute |
28-
| cwd | string | Yes | Working directory (use "." for current) |
29-
| timeout | int | No | Timeout in seconds (default: 30) |
10+
- Commands run in the user's default shell (Unix: ${SHELL} or /bin/sh; Windows: pwsh/powershell or cmd.exe)
11+
- Each call creates a fresh shell session — no state persists between executions
12+
- Default working directory: agent's working directory. Override with "cwd" parameter (absolute or relative paths)
13+
- Default timeout: 30s. Use "timeout" parameter for longer operations (e.g., builds, tests)
3014
3115
## Best Practices
3216
33-
### ✅ DO
34-
- Leverage the "cwd" parameter for directory-specific commands, rather than cding within commands
35-
- Quote arguments containing spaces or special characters
36-
- Use pipes and redirections
37-
- Write advanced scripts with heredocs, that replace a lot of simple commands or tool calls
38-
- This tool is great at reading and writing multiple files at once
39-
- Avoid writing shell scripts to the disk. Instead, use heredocs to pipe the script to the SHELL
40-
- Use the timeout parameter for long-running operations (e.g., builds, tests)
41-
42-
### Git Commits
43-
44-
When user asks to create git commit
45-
46-
- Add "Assisted-By: cagent" as a trailer line in the commit message
47-
- Use the format: git commit -m "Your commit message" -m "" -m "Assisted-By: cagent"
48-
49-
## Usage Examples
50-
51-
**Basic command execution:**
52-
{ "cmd": "ls -la", "cwd": "." }
17+
- Use "cwd" instead of cd within commands
18+
- Quote arguments with spaces or special characters
19+
- Use pipes, redirections, and heredocs to combine operations
20+
- Prefer inline heredocs over writing shell scripts to disk
21+
- For git commits, add trailer: git commit -m "message" -m "" -m "Assisted-By: cagent"
5322
54-
**Long-running command with custom timeout:**
55-
{ "cmd": "npm run build", "cwd": ".", "timeout": 120 }
23+
## Examples
5624
57-
**Language-specific operations:**
5825
{ "cmd": "go test ./...", "cwd": ".", "timeout": 180 }
59-
{ "cmd": "npm install", "cwd": "frontend" }
60-
{ "cmd": "python -m pytest tests/", "cwd": "backend", "timeout": 90 }
61-
62-
**File operations:**
63-
{ "cmd": "find . -name '*.go' -type f", "cwd": "." }
6426
{ "cmd": "grep -r 'TODO' src/", "cwd": "." }
65-
66-
**Process management:**
67-
{ "cmd": "ps aux | grep node", "cwd": "." }
68-
{ "cmd": "docker ps --format 'table {{.Names}}\t{{.Status}}'", "cwd": "." }
69-
70-
**Complex pipelines:**
71-
{ "cmd": "cat package.json | jq '.dependencies'", "cwd": "frontend" }
72-
73-
**Bash scripts:**
74-
{ "cmd": "cat << 'EOF' | ${SHELL}
75-
echo Hello
76-
EOF" }
27+
{ "cmd": "cat << 'EOF' | ${SHELL}\necho Hello\nEOF" }
7728
7829
## Error Handling
7930
80-
Commands that exit with non-zero status codes will return error information along with any output produced before failure.
81-
Commands that exceed their timeout will be terminated automatically.
82-
83-
---
31+
Non-zero exit codes return error info with output. Timed-out commands are terminated automatically.
8432
8533
# Background Jobs
8634
87-
Run long-running processes in the background while continuing with other tasks. Perfect for starting servers, watching files, or any process that needs to run alongside other operations.
88-
89-
## When to Use Background Jobs
90-
91-
**Use background jobs for:**
92-
- Starting web servers, databases, or other services
93-
- Running file watchers or live reload tools
94-
- Long-running processes that other tasks depend on
95-
- Commands that produce continuous output over time
96-
97-
**Don't use background jobs for:**
98-
- Quick commands that complete in seconds
99-
- Commands where you need immediate results
100-
- One-time operations (use regular shell tool instead)
101-
102-
## Background Job Tools
103-
104-
**run_background_job**: Start a command in the background
105-
- Parameters: cmd (required), cwd (optional, defaults to ".")
106-
- Returns: Job ID for tracking
107-
108-
**list_background_jobs**: List all background jobs
109-
- No parameters required
110-
- Returns: Status, runtime, and command for each job
111-
112-
**view_background_job**: View output of a specific job
113-
- Parameters: job_id (required)
114-
- Returns: Current output and job status
115-
116-
**stop_background_job**: Stop a running job
117-
- Parameters: job_id (required)
118-
- Terminates the process and all child processes
119-
120-
## Background Job Workflow
121-
122-
**1. Start a background job:**
123-
{ "cmd": "npm start", "cwd": "frontend" }
124-
→ Returns job ID (e.g., "job_1731772800_1")
125-
126-
**2. Check running jobs:**
127-
Use list_background_jobs to see all jobs with their status
128-
129-
**3. View job output:**
130-
{ "job_id": "job_1731772800_1" }
131-
→ Shows current output and status
132-
133-
**4. Stop job when done:**
134-
{ "job_id": "job_1731772800_1" }
135-
→ Terminates the process and all child processes
136-
137-
## Important Characteristics
138-
139-
**Output Buffering**: Each job captures up to 10MB of output. Beyond this limit, new output is discarded to prevent memory issues.
140-
141-
**Process Groups**: Background jobs and all their child processes are managed as a group. Stopping a job terminates the entire process tree.
142-
143-
**Environment Inheritance**: Jobs inherit environment variables from when they are started. Changes after job start don't affect running jobs.
144-
145-
**Automatic Cleanup**: All background jobs are automatically terminated when the agent stops.
146-
147-
**Job Persistence**: Job history is kept in memory until agent stops. Completed jobs remain queryable.
148-
149-
## Background Job Examples
150-
151-
**Start a web server:**
152-
{ "cmd": "python -m http.server 8000", "cwd": "." }
153-
154-
**Start a development server:**
155-
{ "cmd": "npm run dev", "cwd": "frontend" }
156-
157-
**Run a file watcher:**
158-
{ "cmd": "go run . watch", "cwd": "." }
35+
Use background jobs for long-running processes (servers, watchers) that should run while other tasks are performed.
15936
160-
**Start a database:**
161-
{ "cmd": "docker run --rm -p 5432:5432 postgres:latest", "cwd": "." }
37+
- **run_background_job**: Start a command, returns job ID. Example: { "cmd": "npm run dev", "cwd": "frontend" }
38+
- **list_background_jobs**: Show all jobs with status and runtime
39+
- **view_background_job**: Get output and status of a job by job_id
40+
- **stop_background_job**: Terminate a job and all its child processes by job_id
16241
163-
**Multiple services pattern:**
164-
1. Start backend: run_background_job with server command
165-
2. Start frontend: run_background_job with dev server
166-
3. Perform tasks: use other tools while services run
167-
4. Check logs: view_background_job to see service output
168-
5. Cleanup: stop_background_job for each service (or let agent cleanup automatically)`
42+
**Notes**: Output capped at 10MB per job. Jobs inherit env vars at start time. All jobs auto-terminate when the agent stops.`

pkg/tools/builtin/tasks.go

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,11 @@ func NewTasksTool(storagePath string) *TasksTool {
108108
func (t *TasksTool) Instructions() string {
109109
return `## Using the Tasks Tools
110110
111-
These tools provide persistent task management with priorities, dependencies, and status tracking.
112-
113-
Tasks are persisted to a JSON file so they survive across sessions.
114-
115-
### Key concepts:
116-
- **Priority**: critical > high > medium > low
117-
- **Status**: pending, in_progress, done, blocked
118-
- **Dependencies**: A task is automatically blocked if any of its dependencies are not done
119-
- **Effective status**: The computed status taking dependencies into account
120-
121-
### Workflow:
122-
1. Use create_task to create tasks with titles, descriptions, priorities, and dependencies
123-
2. Use list_tasks to see all tasks sorted by priority (blocked tasks last)
124-
3. Use next_task to find the highest-priority actionable task
125-
4. Use update_task to change status, priority, or other fields as work progresses
126-
5. Use add_dependency / remove_dependency to manage task ordering`
111+
Persistent task management with priorities (critical > high > medium > low), statuses (pending, in_progress, done, blocked), and dependencies.
112+
113+
Tasks are saved to a JSON file and survive across sessions. A task is automatically blocked if any dependency is not done.
114+
115+
Workflow: create_task → list_tasks/next_task → update_task as work progresses. Use add_dependency/remove_dependency to manage ordering.`
127116
}
128117

129118
func (t *TasksTool) load() taskStore {

pkg/tools/builtin/think.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,11 @@ func NewThinkTool() *ThinkTool {
3535
func (t *ThinkTool) Instructions() string {
3636
return `## Using the think tool
3737
38-
Before taking any action or responding to the user after receiving tool results, use the think tool as a scratchpad to:
39-
- List the specific rules that apply to the current request
38+
Use the think tool as a scratchpad before acting or responding. Use it to:
39+
- List rules that apply to the current request
4040
- Check if all required information is collected
41-
- Verify that the planned action complies with all policies
42-
- Iterate over tool results for correctness
43-
44-
## Rules
45-
- Use the think tool generously to jot down thoughts and ideas.`
41+
- Verify planned actions comply with policies
42+
- Iterate over tool results for correctness`
4643
}
4744

4845
func (t *ThinkTool) Tools(context.Context) ([]tools.Tool, error) {

pkg/tools/builtin/user_prompt.go

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -79,51 +79,17 @@ func (t *UserPromptTool) userPrompt(ctx context.Context, params UserPromptArgs)
7979
func (t *UserPromptTool) Instructions() string {
8080
return `## Using the user_prompt tool
8181
82-
Use the user_prompt tool when you need to ask the user a question or gather input interactively.
83-
This tool displays a dialog to the user and waits for their response.
84-
85-
### When to use this tool:
86-
- When you need clarification from the user before proceeding
87-
- When you need to collect specific information (e.g., credentials, preferences, choices)
88-
- When the user needs to make a decision between multiple options
89-
90-
### Schema support:
91-
You can optionally provide a JSON schema to define the expected response structure:
92-
- Object schemas with properties for collecting multiple fields
93-
- Primitive type schemas (string, number, boolean) for simple inputs
94-
- Enum types for presenting a list of choices
95-
- Required fields to ensure necessary information is collected
96-
97-
### Example schemas:
98-
99-
Simple string input:
100-
{
101-
"type": "string",
102-
"title": "API Key",
103-
"description": "Enter your API key"
104-
}
82+
Use user_prompt to ask the user a question or gather input when you need clarification, specific information, or a decision.
10583
106-
Multiple choice:
107-
{
108-
"type": "string",
109-
"enum": ["option1", "option2", "option3"],
110-
"title": "Select an option"
111-
}
84+
Optionally provide a JSON schema to structure the expected response (object, primitive, or enum types).
11285
113-
Object with multiple fields:
114-
{
115-
"type": "object",
116-
"properties": {
117-
"username": {"type": "string", "description": "Your username"},
118-
"remember": {"type": "boolean", "description": "Remember me"}
119-
},
120-
"required": ["username"]
121-
}
86+
Example schema for multiple choice:
87+
{"type": "string", "enum": ["option1", "option2"], "title": "Select an option"}
88+
89+
Example schema for structured input:
90+
{"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}
12291
123-
### Response format:
124-
The tool returns a JSON object with:
125-
- action: "accept" (user provided response), "decline" (user declined), or "cancel" (user cancelled)
126-
- content: The user's response data (only present when action is "accept")`
92+
Response contains "action" (accept/decline/cancel) and "content" (user data, only when accepted).`
12793
}
12894

12995
func (t *UserPromptTool) Tools(context.Context) ([]tools.Tool, error) {

0 commit comments

Comments
 (0)