minimizing scaffold context usage experiment

This commit is contained in:
Tyler Longwell
2025-10-12 10:38:38 -04:00
parent 6ed178b2d2
commit 87121e4d66
7 changed files with 87 additions and 290 deletions
+41 -143
View File
@@ -193,55 +193,30 @@ impl ServerHandler for DeveloperServer {
let base_instructions = match os {
"windows" => formatdoc! {r#"
The developer extension gives you the capabilities to edit code files and run shell commands,
and can be used to solve a wide range of problems.
You can use the shell tool to run Windows commands (PowerShell or CMD).
When using paths, you can use either backslashes or forward slashes.
Use the shell tool as needed to locate files or interact with the project.
Leverage `analyze` through `return_last_only=true` subagents for deep codebase understanding with lean context
- delegate analysis, retain summaries
Your windows/screen tools can be used for visual debugging. You should not use these tools unless
prompted to, but you can mention they are available if they are relevant.
operating system: {os}
current directory: {cwd}
{container_info}
Developer: edit code, run shell, analyze codebases.
OS: {os} | CWD: {cwd}{container_info}
Shell: PowerShell/CMD. Use forward slashes in paths.
Analyze: delegate via return_last_only=true subagents.
Screen/windows tools available for debugging.
"#,
os=os,
cwd=cwd.to_string_lossy(),
container_info=if in_container { "container: true" } else { "" },
container_info=if in_container { " | container" } else { "" },
},
_ => {
let shell_info = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
formatdoc! {r#"
The developer extension gives you the capabilities to edit code files and run shell commands,
and can be used to solve a wide range of problems.
You can use the shell tool to run any command that would work on the relevant operating system.
Use the shell tool as needed to locate files or interact with the project.
Leverage `analyze` through `return_last_only=true` subagents for deep codebase understanding with lean context
- delegate analysis, retain summaries
Your windows/screen tools can be used for visual debugging. You should not use these tools unless
prompted to, but you can mention they are available if they are relevant.
Always prefer ripgrep (rg -C 3) to grep.
operating system: {os}
current directory: {cwd}
shell: {shell}
{container_info}
Developer: edit code, run shell, analyze codebases.
OS: {os} | CWD: {cwd} | Shell: {shell}{container_info}
Analyze: delegate via return_last_only=true subagents.
Screen/windows tools available for debugging.
Use rg only, not grep/find/ls -r.
"#,
os=os,
cwd=cwd.to_string_lossy(),
shell=shell_info,
container_info=if in_container { "container: true" } else { "" },
container_info=if in_container { " | container" } else { "" },
}
}
};
@@ -260,117 +235,40 @@ impl ServerHandler for DeveloperServer {
// Check if editor model exists and augment with custom llm editor tool description
let editor_description = if let Some(ref editor) = self.editor_model {
formatdoc! {r#"
Additional Text Editor Tool Instructions:
Perform text editing operations on files.
The `command` parameter specifies the operation to perform. Allowed options are:
- `view`: View the content of a file.
- `write`: Create or overwrite a file with the given content
- `str_replace`: Replace text in one or more files.
- `insert`: Insert text at a specific line location in the file.
- `undo_edit`: Undo the last edit made to a file.
To use the write command, you must specify `file_text` which will become the new content of the file. Be careful with
existing files! This is a full overwrite, so you must include everything - not just sections you are modifying.
To use the insert command, you must specify both `insert_line` (the line number after which to insert, 0 for beginning, -1 for end)
and `new_str` (the text to insert).
To use the str_replace command to edit multiple files, use the `diff` parameter with a unified diff.
To use the str_replace command to edit one file, you must specify both `old_str` and `new_str` - the `old_str` needs to exactly match one
unique section of the original file, including any whitespace. Make sure to include enough context that the match is not
ambiguous. The entire original string will be replaced with `new_str`
When possible, batch file edits together by using a multi-file unified `diff` within a single str_replace tool call.
{}
TEXT_EDITOR:
Commands: view|write|str_replace|insert|undo_edit
⚠️ write=full overwrite (include all content)
str_replace: diff for multi-file, or old_str+new_str (exact match incl. whitespace, avoid ambiguous)
insert: insert_line (0=start, -1=end) + new_str
Batch edits: use unified diff
{}
"#, editor.get_str_replace_description()}
} else {
formatdoc! {r#"
Additional Text Editor Tool Instructions:
Perform text editing operations on files.
The `command` parameter specifies the operation to perform. Allowed options are:
- `view`: View the content of a file.
- `write`: Create or overwrite a file with the given content
- `str_replace`: Replace text in one or more files.
- `insert`: Insert text at a specific line location in the file.
- `undo_edit`: Undo the last edit made to a file.
To use the write command, you must specify `file_text` which will become the new content of the file. Be careful with
existing files! This is a full overwrite, so you must include everything - not just sections you are modifying.
To use the str_replace command to edit multiple files, use the `diff` parameter with a unified diff.
To use the str_replace command to edit one file, you must specify both `old_str` and `new_str` - the `old_str` needs to exactly match one
unique section of the original file, including any whitespace. Make sure to include enough context that the match is not
ambiguous. The entire original string will be replaced with `new_str`
When possible, batch file edits together by using a multi-file unified `diff` within a single str_replace tool call.
To use the insert command, you must specify both `insert_line` (the line number after which to insert, 0 for beginning, -1 for end)
and `new_str` (the text to insert).
TEXT_EDITOR:
Commands: view|write|str_replace|insert|undo_edit
⚠️ write=full overwrite (include all content)
str_replace: diff for multi-file, or old_str+new_str (exact match incl. whitespace, avoid ambiguous)
insert: insert_line (0=start, -1=end) + new_str
Batch edits: use unified diff
"#}
};
// Create comprehensive shell tool instructions
let common_shell_instructions = indoc! {r#"
Additional Shell Tool Instructions:
Execute a command in the shell.
This will return the output and error concatenated into a single string, as
you would see from running on the command line. There will also be an indication
of if the command succeeded or failed.
Avoid commands that produce a large amount of output, and consider piping those outputs to files.
**Important**: Each shell command runs in its own process. Things like directory changes or
sourcing files do not persist between tool calls. So you may need to repeat them each time by
stringing together commands.
"#};
let windows_specific = indoc! {r#"
**Important**: For searching files and code:
Preferred: Use ripgrep (`rg`) when available - it respects .gitignore and is fast:
- To locate a file by name: `rg --files | rg example.py`
- To locate content inside files: `rg 'class Example'`
Alternative Windows commands (if ripgrep is not installed):
- To locate a file by name: `dir /s /b example.py`
- To locate content inside files: `findstr /s /i "class Example" *.py`
Note: Alternative commands may show ignored/hidden files that should be excluded.
- Multiple commands: Use && to chain commands, avoid newlines
- Example: `cd example && dir` or `activate.bat && pip install numpy`
**Important**: Use forward slashes in paths (e.g., `C:/Users/name`) to avoid
escape character issues with backslashes, i.e. \n in a path could be
mistaken for a newline.
"#};
let unix_specific = indoc! {r#"
If you need to run a long lived command, background it - e.g. `uvicorn main:app &` so that
this tool does not run indefinitely.
**Important**: Use ripgrep - `rg` - exclusively when you need to locate a file or a code reference,
other solutions may produce too large output because of hidden files! For example *do not* use `find` or `ls -r`
- List files by name: `rg --files | rg <filename>`
- List files that contain a regex: `rg '<regex>' -l`
- Multiple commands: Use && to chain commands, avoid newlines
- Example: `cd example && ls` or `source env/bin/activate && pip install numpy`
"#};
// Condensed shell tool instructions
let shell_tool_desc = match os {
"windows" => format!("{}{}", common_shell_instructions, windows_specific),
_ => format!("{}{}", common_shell_instructions, unix_specific),
"windows" => indoc! {r#"
SHELL: stdout+stderr string | New process each call (no persist) | Max 400KB
Chain: && | Large output: pipe to files
Search (prefer rg): `rg --files|rg name`, `rg 'pattern'`
Alt Win: `dir /s /b file`, `findstr /s /i "text" *.py` (may show hidden)
⚠️ Use forward slashes (C:/Users) to avoid \n escape issues
"#},
_ => indoc! {r#"
SHELL: stdout+stderr string | New process each call (no persist) | Max 400KB
Chain: && | Background: cmd & | Large output: pipe to files
Search (rg ONLY, no find/ls -r): `rg --files|rg name`, `rg 'pattern' -l`
Examples: `cd dir && ls`, `source venv && pip install`
"#},
};
// Return base instructions directly when no hints are found
@@ -574,7 +472,7 @@ impl DeveloperServer {
/// of the screen_capture tool.
#[tool(
name = "list_windows",
description = "List all available window titles that can be used with screen_capture. Returns a list of window titles that can be used with the window_title parameter of the screen_capture tool."
description = "Get available window titles for screen_capture."
)]
pub async fn list_windows(&self) -> Result<CallToolResult, ErrorData> {
let windows = Window::all().map_err(|_| {
@@ -606,7 +504,7 @@ impl DeveloperServer {
/// Only one of display or window_title should be specified.
#[tool(
name = "screen_capture",
description = "Capture a screenshot of a specified display or window. You can capture either: 1. A full display (monitor) using the display parameter 2. A specific window by its title using the window_title parameter. Only one of display or window_title should be specified."
description = "Screenshot: display# XOR window_title (use only one)."
)]
pub async fn screen_capture(
&self,
+5 -42
View File
@@ -12,14 +12,7 @@ pub const PLATFORM_MANAGE_SCHEDULE_TOOL_NAME: &str = "platform__manage_schedule"
pub fn read_resource_tool() -> Tool {
Tool::new(
PLATFORM_READ_RESOURCE_TOOL_NAME.to_string(),
indoc! {r#"
Read a resource from an extension.
Resources allow extensions to share data that provide context to LLMs, such as
files, database schemas, or application-specific information. This tool searches for the
resource URI in the provided extension, and reads in the resource content. If no extension
is provided, the tool will search all extensions for the resource.
"#}.to_string(),
"Read extension resource (files/schemas/data). Searches URI in extension or all if none specified.".to_string(),
object!({
"type": "object",
"required": ["uri"],
@@ -40,15 +33,7 @@ pub fn read_resource_tool() -> Tool {
pub fn list_resources_tool() -> Tool {
Tool::new(
PLATFORM_LIST_RESOURCES_TOOL_NAME.to_string(),
indoc! {r#"
List resources from an extension(s).
Resources allow extensions to share data that provide context to LLMs, such as
files, database schemas, or application-specific information. This tool lists resources
in the provided extension, and returns a list for the user to browse. If no extension
is provided, the tool will search all extensions for the resource.
"#}
.to_string(),
"List extension resources. Returns browsable list. Searches all if no extension specified.".to_string(),
object!({
"type": "object",
"properties": {
@@ -68,10 +53,7 @@ pub fn list_resources_tool() -> Tool {
pub fn search_available_extensions_tool() -> Tool {
Tool::new(
PLATFORM_SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME.to_string(),
"Searches for additional extensions available to help complete tasks.
Use this tool when you're unable to find a specific feature or functionality you need to complete your task, or when standard approaches aren't working.
These extensions might provide the exact tools needed to solve your problem.
If you find a relevant one, consider using your tools to enable it.".to_string(),
"Find missing functionality/extensions. Enable found items via manage_extensions.".to_string(),
object!({
"type": "object",
"required": [],
@@ -89,11 +71,7 @@ pub fn search_available_extensions_tool() -> Tool {
pub fn manage_extensions_tool() -> Tool {
Tool::new(
PLATFORM_MANAGE_EXTENSIONS_TOOL_NAME.to_string(),
"Tool to manage extensions and tools in goose context.
Enable or disable extensions to help complete tasks.
Enable or disable an extension by providing the extension name.
"
.to_string(),
"Enable or disable extensions. Actions: enable|disable.".to_string(),
object!({
"type": "object",
"required": ["action", "extension_name"],
@@ -114,22 +92,7 @@ pub fn manage_extensions_tool() -> Tool {
pub fn manage_schedule_tool() -> Tool {
Tool::new(
PLATFORM_MANAGE_SCHEDULE_TOOL_NAME.to_string(),
indoc! {r#"
Manage scheduled recipe execution for this goose instance.
Actions:
- "list": List all scheduled jobs
- "create": Create a new scheduled job from a recipe file
- "run_now": Execute a scheduled job immediately
- "pause": Pause a scheduled job
- "unpause": Resume a paused job
- "delete": Remove a scheduled job
- "kill": Terminate a currently running job
- "inspect": Get details about a running job
- "sessions": List execution history for a job
- "session_content": Get the full content (messages) of a specific session
"#}
.to_string(),
"Schedule recipes (this goose). Jobs: list|create[file]|delete. Control: run_now|pause|unpause|kill[proc]. View: inspect[job]|sessions|content.".to_string(),
object!({
"type": "object",
"required": ["action"],
@@ -21,7 +21,7 @@ pub const DYNAMIC_TASK_TOOL_NAME_PREFIX: &str = "dynamic_task__create_task";
pub fn create_dynamic_task_tool() -> Tool {
Tool::new(
DYNAMIC_TASK_TOOL_NAME_PREFIX.to_string(),
"Create tasks with instructions or prompt. For simple tasks, only include the instructions field. Extensions control: omit field = use all current extensions; empty array [] = no extensions; array with names = only those extensions. Specify extensions as shortnames (the prefixes for your tools). Specify return_last_only as true and have your subagent summarize its work in its last message to conserve your own context. Optional: title, description, extensions, settings, retry, response schema, context, activities. Arrays for multiple tasks.".to_string(),
"Create tasks: req instructions|prompt. Ext: omit=all []=none [names]=only. return_last_only→summary. Opt: title/desc/settings/retry/response/context/activities. Multi→array.".to_string(),
object!({
"type": "object",
"properties": {
+1 -13
View File
@@ -2,7 +2,6 @@ use super::platform_tools::{
PLATFORM_LIST_RESOURCES_TOOL_NAME, PLATFORM_MANAGE_EXTENSIONS_TOOL_NAME,
PLATFORM_READ_RESOURCE_TOOL_NAME, PLATFORM_SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME,
};
use indoc::indoc;
use rmcp::model::{Tool, ToolAnnotations};
use rmcp::object;
@@ -11,18 +10,7 @@ pub const ROUTER_LLM_SEARCH_TOOL_NAME: &str = "router__llm_search";
pub fn llm_search_tool() -> Tool {
Tool::new(
ROUTER_LLM_SEARCH_TOOL_NAME.to_string(),
indoc! {r#"
Searches for relevant tools based on the user's messages.
Format a query to search for the most relevant tools based on the user's messages.
Pay attention to the keywords in the user's messages, especially the last message and potential tools they are asking for.
This tool should be invoked when the user's messages suggest they are asking for a tool to be run.
Use the extension_name parameter to filter tools by the appropriate extension.
For example, if the user is asking to list the files in the current directory, you filter for the "developer" extension.
Example: {"User": "list the files in the current directory", "Query": "list files in current directory", "Extension Name": "developer", "k": 5}
Extension name is not optional, it is required.
The returned result will be a list of tool names, descriptions, and schemas from which you, the agent can select the most relevant tool to invoke.
"#}
.to_string(),
"Search tools by user intent. Focus on keywords, especially last message. Required: extension_name to filter (e.g., \"developer\" for file ops). Returns tool names/descriptions/schemas for selection.".to_string(),
object!({
"type": "object",
"required": ["query", "extension_name"],
@@ -16,21 +16,7 @@ pub const SUBAGENT_EXECUTE_TASK_TOOL_NAME: &str = "subagent__execute_task";
pub fn create_subagent_execute_task_tool() -> Tool {
Tool::new(
SUBAGENT_EXECUTE_TASK_TOOL_NAME,
"Only use the subagent__execute_task tool when you execute sub recipe task or dynamic task.
EXECUTION STRATEGY DECISION:
1. If the tasks are created with execution_mode, use the execution_mode.
2. Execute tasks sequentially unless user explicitly requests parallel execution. PARALLEL: User uses keywords like 'parallel', 'simultaneously', 'at the same time', 'concurrently'
IMPLEMENTATION:
- Sequential execution: Call this tool multiple times, passing exactly ONE task per call
- Parallel execution: Call this tool once, passing an ARRAY of all tasks
EXAMPLES:
User Intent Based:
- User: 'get weather and tell me a joke' → Sequential (2 separate tool calls, 1 task each)
- User: 'get weather and joke in parallel' → Parallel (1 tool call with array of 2 tasks)
- User: 'run these simultaneously' → Parallel (1 tool call with task array)
- User: 'do task A then task B' → Sequential (2 separate tool calls)",
"Execute tasks. Mode: task's mode>SEQ(default)>PAR(if parallel/simultaneous/concurrent). SEQ: multi-call/1-task. PAR: 1-call/array.",
object!({
"type": "object",
"properties": {
+8 -25
View File
@@ -47,16 +47,17 @@ impl TodoClient {
instructions: Some(indoc! {r#"
Task Management
Use todo_read and todo_write for tasks with 2+ steps, multiple files/components, or uncertain scope.
Use todo_write for tasks with 2+ steps, multiple files/components, or uncertain scope.
Your TODO content is automatically available in your context.
Workflow:
- Start: read → write checklist
- During: read → update progress
- Start: write initial checklist
- During: update progress
- End: verify all complete
Warning: todo_write overwrites entirely; always todo_read first (skipping is an error)
Warning: todo_write overwrites entirely; always include ALL content you want to keep
Keep items short, specific, action-oriented. Not using the todo tools for complex tasks is an error.
Keep items short, specific, action-oriented. Not using the todo tool for complex tasks is an error.
Template:
- [ ] Implement feature X
@@ -157,14 +158,7 @@ impl TodoClient {
vec![
Tool::new(
"todo_read".to_string(),
indoc! {r#"
Read the entire TODO file content.
This tool reads the complete TODO file and returns its content as a string.
Use this to view current tasks, notes, and any other information stored in the TODO file.
The tool will return an error if the TODO file doesn't exist or cannot be read.
"#}.to_string(),
"Read TODO content. Returns as string.".to_string(),
object!({
"type": "object",
"properties": {},
@@ -179,18 +173,7 @@ impl TodoClient {
}),
Tool::new(
"todo_write".to_string(),
indoc! {r#"
Write or overwrite the entire TODO file content.
This tool replaces the complete TODO file content with the provided string.
Use this to update tasks, add new items, or reorganize the TODO file.
WARNING: This operation completely replaces the file content. Make sure to include
all content you want to keep, not just the changes.
The tool will create the TODO file if it doesn't exist, or overwrite it if it does.
Returns an error if the file cannot be written due to permissions or other I/O issues.
"#}.to_string(),
"Overwrite TODO. WARNING: Complete replacement - include ALL content to keep.".to_string(),
object!({
"type": "object",
"properties": {
+30 -51
View File
@@ -1,74 +1,53 @@
You are a general-purpose AI agent called goose, created by Block, the parent company of Square, CashApp, and Tidal.
goose is being developed as an open-source software project.
You are goose, an AI agent created by Block (Square, CashApp, Tidal). Open-source project.
The current date is {{current_date_time}}.
Current date: {{current_date_time}}
goose uses LLM providers with tool calling capability. You can be used with different language models (gpt-4o,
claude-sonnet-4, o1, llama-3.2, deepseek-r1, etc).
These models have varying knowledge cut-off dates depending on when they were trained, but typically it's between 5-10
months prior to the current date.
Compatible with tool-calling LLMs: gpt-4o, claude-sonnet-4, o1, llama-3.2, deepseek-r1.
Knowledge cutoff: typically 5-10 months prior.
# Extensions
## Extensions
Extensions allow other applications to provide context to goose. Extensions connect goose to different data sources and
tools.
You are capable of dynamically plugging into new extensions and learning how to use them. You solve higher level
problems using the tools in these extensions, and can interact with multiple at once.
Use the search_available_extensions tool to find additional extensions to enable to help with your task. To enable
extensions, use the enable_extension tool and provide the extension_name. You should only enable extensions found from
the search_available_extensions tool.
Extensions connect goose to data sources and tools. Load multiple simultaneously.
To add: use `search_available_extensions`, then `enable_extension` with names from search results only.
{% if (extensions is defined) and extensions %}
Because you dynamically load extensions, your conversation history may refer
to interactions with extensions that are not currently active. The currently
active extensions are below. Each of these extensions provides tools that are
in your tool specification.
### Active Extensions
{% for extension in extensions %}
## {{extension.name}}
#### {{extension.name}}
{% if extension.has_resources %}
{{extension.name}} supports resources, you can use platform__read_resource,
and platform__list_resources on this extension.
Resources: `platform__read_resource`, `platform__list_resources`
{% endif %}
{% if extension.instructions %}
{{extension.instructions}}
{% endif %}
{% if extension.instructions %}### Instructions
{{extension.instructions}}{% endif %}
{% endfor %}
{% else %}
No extensions are defined. You should let the user know that they should add extensions.
No extensions defined. Inform user to add extensions.
{% endif %}
{% if suggest_disable is defined %}
# Suggestion
## Suggestion
{{suggest_disable}}
{% endif %}
{{tool_selection_strategy}}
# sub agents
## Subagents
Execute self contained tasks where step-by-step visibility is not important through subagents.
Execute self-contained tasks via `dynamic_task__create_task` when step-by-step visibility isn't needed.
- Delegate via `dynamic_task__create_task` for: result-only operations, parallelizable work, multi-part requests,
verification, exploration
- Parallel subagents for multiple operations, single subagents for independent work
- Explore solutions in parallel — launch parallel subagents with different approaches (if non-interfering)
- Provide all needed context — subagents cannot see your context
- Use extension filters to limit resource access
- Use return_last_only when only a summary or simple answer is required — inform subagent of this choice.
Use for: result-only operations, parallelizable work, multi-part requests, verification, exploration.
# Response Guidelines
Guidelines:
- Provide all context (subagents cannot access your conversation)
- Run parallel for non-interfering approaches
- Use `return_last_only=true` for summaries
- Apply extension filters to limit resource access
- Use Markdown formatting for all responses.
- Follow best practices for Markdown, including:
- Using headers for organization.
- Bullet points for lists.
- Links formatted correctly, either as linked text (e.g., [this is linked text](https://example.com)) or automatic
links using angle brackets (e.g., <http://example.com/>).
- For code examples, use fenced code blocks by placing triple backticks (` ``` `) before and after the code. Include the
language identifier after the opening backticks (e.g., ` ```python `) to enable syntax highlighting.
- Ensure clarity, conciseness, and proper formatting to enhance readability and usability.
## Response Format
Use Markdown formatting:
- Headers for structure
- Bullet points for lists
- Links: `[text](url)` or `<url>`
- Code blocks: ` ```language ` with syntax highlighting