Files
sunyueandCursor 1368a587ca feat: add required_permissions support for Shell sandbox policy
The Shell tool schema lacked a `required_permissions` parameter,
preventing models from requesting elevated sandbox permissions
(e.g. unrestricted network access). This adds:

- `required_permissions` parameter to the Shell tool schema in tools.json
- Sandboxing instructions in the Shell tool description so models know
  when and how to request permissions
- `shell_sandbox_policy()` in request.rs to map the parameter to the
  protobuf `SandboxPolicy.requested_sandbox_policy` field

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 18:59:25 +08:00

933 lines
63 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"tools": [
{
"type": "function",
"function": {
"name": "AskQuestion",
"description": "Collect structured multiple-choice answers from the user. Use this tool only when you are blocked on a decision that is genuinely the user's to make: one you cannot resolve from the request, the code, or sensible defaults.\n\nUsage notes:\n- Each question should have at least 2 options for the user to choose from\n- Users will always be able to select \"Other\" to provide custom text input\n- Use allow_multiple: true to allow multiple answers to be selected for a question\n- If you recommend a specific option, make that the first option in the list and add \"(Recommended)\" at the end of the label\n\nPrefer this tool over listing options in your final response text (as letters, numbers, bullet points, etc).",
"parameters": {
"type": "object",
"properties": {
"questions": {
"description": "Array of questions to present to the user (minimum 1 required)",
"items": {
"properties": {
"allow_multiple": {
"description": "If true, user can select multiple options. Defaults to false.",
"type": "boolean"
},
"id": {
"description": "Unique identifier for this question",
"type": "string"
},
"options": {
"description": "Array of answer options (minimum 2 required)",
"items": {
"properties": {
"id": {
"description": "Unique identifier for this option",
"type": "string"
},
"label": {
"description": "Display text for this option",
"type": "string"
}
},
"required": [
"id",
"label"
],
"type": "object"
},
"minItems": 2,
"type": "array"
},
"prompt": {
"description": "The question text to display to the user, without the options.",
"type": "string"
}
},
"required": [
"id",
"prompt",
"options"
],
"type": "object"
},
"minItems": 1,
"type": "array"
},
"title": {
"description": "Optional title for the questions form",
"type": "string"
}
},
"required": [
"questions"
]
}
}
},
{
"type": "function",
"function": {
"name": "AwaitShell",
"description": "Check or poll a backgrounded shell job. For work that does not have a shell id, you can omit the shell_id arg to sleep for the full `block_until_ms` duration (prefer this over sleeping in the shell, because it renders nicely to the user). At the end of your turn, you will be notified about any unawaited jobs that completed. If you think a job completed (e.g. because you killed it), observe it with AwaitShell to skip the notification, because stale notifications can confuse the user.\n\nPrefer NOT to poll reflexively with AwaitShell. Multitask on independent work while backgrounded jobs run, or finish your turn and rely on the end-of-turn completion notification. Poll with AwaitShell only when one of the following is true:\n- Your very next step is blocked on this specific job's result and you have no other productive work to do, OR\n- The task requires close monitoring (see shell guidance below).\n- Never poll a task whose tool result says it was \"manually backgrounded by the user\".\n- NEVER USE THIS TO POLL OR WAIT VACUOUSLY FOR A SUBAGENT LAUNCHED WITH THE Task TOOL — rely on the end-of-turn completion notification instead (it is delivered as soon as the subagent finishes; guessing a wait time is inefficient).\n- Shell: only poll with AwaitShell when the command requires close monitoring. Close monitoring means a long-running job that can silently hang, degrade, or need a course correction before it completes — e.g. training runs, eval runs, deployments, long builds, datagen pipelines, DB migrations, large data transfers. For fire-and-forget commands (tests, installs, dev servers/watchers, short scripts, etc.) the completion notification is enough — start them, keep working, and only poll with AwaitShell later if you end up blocked on the result.\n- Shell sanity check (regardless of close monitoring): when you spawn a command directly into the background (`block_until_ms: 0`), do a single status check by reading the output file to confirm the command didn't fail to start. This is a one-shot smoke check, not a polling loop.\n- Shell close-monitoring guidance (only applies in the close-monitoring case above):\n - HARD STOPPING CONSTRAINT: once you've decided to actively poll, don't stop until (a) the job terminates, (b) the command reaches a healthy steady state (only for non-terminating commands, e.g. dev server/watcher), or (c) the command is hung — follow the hang guidance below.\n - Waiting until a regex matches the output can be useful for e.g. known startup/status/error logs.\n - Size `block_until_ms` to the command's expected runtime. When waiting further, avoid waiting 1h or more: prefer slices of 60s-59m (keeps prompt cache warm). Size slices based on expected progress; when progress is unclear, exponential backoff is useful.\n - Output file header has `pid` and `running_for_ms` (updated every 5000ms).\n - When finished, footer with `exit_code` and `elapsed_ms` appears (regex only matches the body, not header/footer).\n - If the command is taking longer than expected and appears hung (use judgment based on command type), kill the process if safe to do so using the pid in the header. If possible, fix the hang and proceed.",
"parameters": {
"type": "object",
"properties": {
"block_until_ms": {
"description": "Max sleep time to block before returning (in milliseconds). Defaults to 30000ms. Set to 0 for non-blocking status check. Must not exceed 7140000 (119 minutes).",
"maximum": 7140000,
"type": "number"
},
"pattern": {
"description": "Block until the regex matches stdout/stderr stream (or task completes). Matches anywhere in the shell output, not just new output. Will not match terminal file headers or footers, e.g. exit_code. Accepts JavaScript regex patterns (compiled with the multiline `m` flag).",
"type": "string"
},
"shell_id": {
"description": "Optional shell id to poll. If omitted, this tool sleeps for the full block_until_ms duration and then returns. Required when block_until_ms is 0.",
"type": "string"
},
"waiting_for_subagent": {
"description": "Set this to true if you are waiting for subagent(s) to complete. Remember you should NOT be doing this and instead end your turn or do parallel work.",
"type": "boolean"
}
}
}
}
},
{
"type": "function",
"function": {
"name": "CallMcpTool",
"description": "Call an MCP tool by server identifier and tool name with arbitrary JSON arguments. Use the matching descriptor in <mcp_meta_tools>: follow its inline input_schema, or read its definition_path when the schema is stored in a file. Call listed tools directly; do not call GetMcpTools first. If Cursor returns an MCP error, inspect it, correct the arguments or authentication, and retry only when appropriate.\n\nExample:\n{\n \"server\": \"my-mcp-server\",\n \"toolName\": \"search\",\n \"description\": \"Search the public docs for the example API\",\n \"arguments\": { \"query\": \"example\", \"limit\": 10 }\n}",
"parameters": {
"type": "object",
"properties": {
"arguments": {
"description": "Arguments to pass to the MCP tool, as described in the tool descriptor.",
"type": "object"
},
"description": {
"description": "Short plain-language description of what this call will do. One sentence naming the outcome and where it applies (channel, page, file, or service) when known. Do not include tool names, argument keys, or JSON.",
"type": "string"
},
"requestSmartModeApproval": {
"description": "Set to true when immediately retrying the exact same MCP call after Auto-review blocks it and you decide the user should approve it through the native approval card.",
"type": "boolean"
},
"server": {
"description": "Identifier of the MCP server hosting the tool.",
"type": "string"
},
"smartModeBlockReason": {
"description": "Provide the exact block reason returned by Auto-review in the prior rejection. Required when requestSmartModeApproval is true so the approval card shows the original classifier reason without re-running the classifier.",
"type": "string"
},
"toolName": {
"description": "Name of the MCP tool to invoke.",
"type": "string"
}
},
"required": [
"server",
"toolName"
]
}
}
},
{
"type": "function",
"function": {
"name": "SembleSearch",
"description": "Search a source repository with hybrid semantic retrieval, BM25 lexical matching, and exact-symbol lookup. Use it to locate unknown implementations, understand behavior, find symbols and relevant code, or identify likely entry points in a code flow. The repository may be an absolute local directory or an explicit HTTP(S) Git URL.\n\nWrite natural-language queries in English because the code-specialized model performs best in English; preserve exact identifiers, literals, and code fragments unchanged. Prefer a focused query, start with top_k 5 and 8-12 snippet lines, and keep the default code scope unless documentation or configuration is specifically relevant. Results are ranked evidence, not an exhaustive text match or authoritative call graph; use Grep when every exact occurrence is required, and use SembleFindRelated to expand from a known result.",
"parameters": {
"type": "object",
"properties": {
"description": {
"description": "Short plain-language description of what this search will find. One sentence; do not include tool names or argument keys.",
"type": "string"
},
"repo": {
"description": "Absolute local repository directory or explicit HTTP(S) Git URL.",
"type": "string"
},
"query": {
"description": "Focused English behavior description, exact symbol name, literal, or code fragment.",
"type": "string"
},
"content": {
"description": "Content scope. Use all sparingly because it broadens and weakens ranking.",
"enum": ["code", "docs", "config", "all"],
"type": "string",
"default": "code"
},
"top_k": {
"description": "Number of ranked chunks to return.",
"type": "integer",
"minimum": 1,
"default": 5
},
"max_snippet_lines": {
"description": "Maximum source lines returned per result. Use 0 for locations only.",
"type": "integer",
"minimum": 0,
"default": 10
}
},
"required": ["repo", "query"]
}
}
},
{
"type": "function",
"function": {
"name": "SembleFindRelated",
"description": "Find code chunks semantically related to a known Semble search result. Use it after SembleSearch when a relevant location is known and you need nearby responsibilities, collaborators, or likely connected implementation. Pass the file path exactly as returned by search and a one-indexed line inside that result. This is ranked related-code evidence rather than an authoritative call graph.",
"parameters": {
"type": "object",
"properties": {
"description": {
"description": "Short plain-language description of the relationship being explored. One sentence; do not include tool names or argument keys.",
"type": "string"
},
"repo": {
"description": "The same absolute local repository directory or explicit HTTP(S) Git URL used for search.",
"type": "string"
},
"file_path": {
"description": "File path exactly as returned by SembleSearch.",
"type": "string"
},
"line": {
"description": "One-indexed line contained by the source result.",
"type": "integer",
"minimum": 1
},
"content": {
"description": "Content scope containing the source file.",
"enum": ["code", "docs", "config", "all"],
"type": "string",
"default": "code"
},
"top_k": {
"description": "Number of ranked related chunks to return.",
"type": "integer",
"minimum": 1,
"default": 5
},
"max_snippet_lines": {
"description": "Maximum source lines returned per result. Use 0 for locations only.",
"type": "integer",
"minimum": 0,
"default": 10
}
},
"required": ["repo", "file_path", "line"]
}
}
},
{
"function": {
"description": "Use this tool to create or revise a concise plan for accomplishing the user's request. This tool should be called at the end of the planning phase to finalize and store the plan.\n\nThe plan you create should be properly formatted in markdown, using appropriate sections and headers. The plan should be very concise and actionable, providing the minimum amount of detail for the user to understand and action the plan. It may be helpful to identify the most important couple files you will change, and existing code you will leverage. Cite specific file paths and essential snippets of code. IMPORTANT: Do NOT use markdown tables in plan content (they cannot be rendered for the user); use bullet lists instead. The first line MUST BE A TITLE for the plan formatted as a level 1 markdown heading.\n\nTASK ORGANIZATION:\n\nUse 'todos' for organizing implementation tasks:\n- Each todo should be a clear, specific, and actionable task\n- Each todo needs a unique ID (e.g., \"setup-auth\") and descriptive content\n- If the plan is simple, provide just a few high-level todos or none at all\n\nUPDATING THE PLAN:\n- The plan file URI will be returned in the tool result\n- If a current plan already exists, call this tool with the complete revised plan and omit the name field\n- Only the first CreatePlan call may include name; later calls must not include name and must not use name to rename or create a separate plan\n- If the user asks for a separate new plan while a current plan exists, explain the limitation or ask how to proceed before calling CreatePlan again\n\nAdditional guidelines:\n- Avoid asking clarifying questions in the plan itself. Ask them before calling this tool. Present these to the user using the AskQuestion tool.\n- Todos help break down complex plans into manageable, trackable tasks\n- Focus on high-level meaningful decisions rather than low-level implementation details\n- A good plan is glanceable, not a wall of text.",
"name": "CreatePlan",
"parameters": {
"properties": {
"name": {
"description": "A short 3-4 word name for the plan. IMPORTANT: Provide this only on the first CreatePlan call when no current plan exists. If a current plan already exists, omit this field entirely; do not use it to rename or create a separate plan.",
"type": "string"
},
"overview": {
"description": "A 1-2 sentence high-level description of the plan that summarizes what will be accomplished",
"type": "string"
},
"plan": {
"description": "A detailed, concrete plan for accomplishing the user's request",
"type": "string"
},
"todos": {
"description": "Array of implementation todos",
"items": {
"properties": {
"content": {
"description": "Description of the todo task",
"type": "string"
},
"id": {
"description": "Unique identifier for the todo",
"type": "string"
}
},
"required": [
"id",
"content"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "function"
},
{
"type": "function",
"function": {
"name": "Delete",
"description": "Deletes a file at the specified path. The operation will fail gracefully if:\n - The file doesn't exist\n - The operation is rejected for security reasons\n - The file cannot be deleted",
"parameters": {
"type": "object",
"properties": {
"path": {
"description": "The absolute path of the file to delete",
"type": "string"
}
},
"required": [
"path"
]
}
}
},
{
"type": "function",
"function": {
"name": "EditNotebook",
"description": "Use this tool to edit a jupyter notebook cell.\nCell indices are 0-based. 'old_string' and 'new_string' should be a valid cell content, i.e. WITHOUT any JSON syntax that notebook files use under the hood. If you need to create a new notebook, just set 'is_new_cell' to true and cell_idx to 0.",
"parameters": {
"type": "object",
"properties": {
"cell_idx": {
"description": "The index of the cell to edit (0-based)",
"type": "number"
},
"cell_language": {
"description": "The language of the cell to edit. Should be STRICTLY one of these: 'python', 'markdown', 'javascript', 'typescript', 'r', 'sql', 'shell', 'raw' or 'other'.",
"type": "string"
},
"is_new_cell": {
"description": "If true, a new cell will be created at the specified cell index. If false, the cell at the specified cell index will be edited.",
"type": "boolean"
},
"new_string": {
"description": "The edited text to replace the old_string or the content for the new cell.",
"type": "string"
},
"old_string": {
"description": "The text to replace (must be unique within the cell, and must match the cell contents exactly, including all whitespace and indentation).",
"type": "string"
},
"target_notebook": {
"description": "The path to the notebook file you want to edit. You can use either a relative path in the workspace or an absolute path. If an absolute path is provided, it will be preserved as is.",
"type": "string"
}
},
"required": [
"target_notebook",
"cell_idx",
"is_new_cell",
"cell_language",
"old_string",
"new_string"
]
}
}
},
{
"type": "function",
"function": {
"name": "FetchMcpResource",
"description": "Reads a specific resource from an MCP server, identified by server name and resource URI. Optionally, set downloadPath (relative to the workspace) to save the resource to disk; when set, the resource will be downloaded and not returned to the model.",
"parameters": {
"type": "object",
"properties": {
"downloadPath": {
"description": "Optional relative path in the workspace to save the resource to. When set, the resource is written to disk and is not returned to the model.",
"type": "string"
},
"requestSmartModeApproval": {
"description": "Set to true when immediately retrying the exact same resource fetch after Auto-review blocks it and you decide the user should approve it through the native approval card.",
"type": "boolean"
},
"server": {
"description": "The MCP server identifier",
"type": "string"
},
"smartModeBlockReason": {
"description": "Provide the exact block reason returned by Auto-review in the prior rejection. Required when requestSmartModeApproval is true so the approval card shows the original classifier reason without re-running the classifier.",
"type": "string"
},
"uri": {
"description": "The resource URI to read",
"type": "string"
}
},
"required": [
"server",
"uri"
]
}
}
},
{
"type": "function",
"function": {
"name": "GenerateImage",
"description": "Generate an image file from a text description.\n\nSTRICT INVOCATION RULES (must follow):\n- Only use this tool when the user explicitly asks for an image. Do not generate images \"just to be helpful\".\n- Do not use this tool for data heavy visualizations such as charts, plots, tables.\n\nGeneral guidelines:\n- Provide a concrete description first: subject(s), layout, style, colors, text (if any), and constraints.\n- If the user requests an aspect ratio, set `aspect_ratio` to one of \"1:1\", \"4:3\", \"3:4\", \"16:9\", or \"9:16\".\n- If the user provides reference images, include them in `reference_image_paths`.\n- Do not repeat generated images as Markdown in your response; the client displays tool-generated images automatically.\n\nExamples that should call this tool:\n- user: \"Generate an app icon for a note-taking app, minimal flat vector style.\" (explicitly requests an image asset)\n- user: \"Make a UI mockup of a settings screen with a dark mode toggle.\" (explicitly requests a UI mockup)\n- user: \"Generate an asset of a game character with a sword.\" (explicitly requests a visual asset)\n\nExamples that should not call this tool:\n- user: \"Create a plan to refactor this module.\" (planning request; respond in text or mermaid diagram)\n- user: \"Generate a chart of sales and revenue using data.csv.\" (data visualization; generate via code)\n",
"parameters": {
"type": "object",
"properties": {
"aspect_ratio": {
"description": "Optional aspect ratio for the generated image. Supported values are \"1:1\", \"4:3\", \"3:4\", \"16:9\", and \"9:16\".",
"enum": [
"1:1",
"4:3",
"3:4",
"16:9",
"9:16"
],
"type": "string"
},
"description": {
"description": "A detailed description of the image.",
"type": "string"
},
"filename": {
"description": "Optional filename for the generated image (e.g., 'diagram.png'). Do not include a directory path - the tool automatically handles where to save and how to display the image. If not provided, a timestamped filename will be generated.",
"type": "string"
},
"reference_image_paths": {
"description": "Optional array of file paths to reference images as additional inputs.",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"description"
]
}
}
},
{
"type": "function",
"function": {
"name": "GetMcpTools",
"description": "Inspect the Cursor client's current MCP server state. Use this only when a server or tool is absent from <mcp_meta_tools>, when its descriptor has neither an inline schema nor a readable definition_path, or when you specifically need refreshed connection/authentication status. Do not call it before tools already described in <mcp_meta_tools>.\n\n1. {\"server\":\"<id>\"}: returns the server status, instructions, descriptions, and schemas.\n2. {\"server\":\"<id>\",\"toolName\":\"<name>\"}: returns one tool.\n3. {\"pattern\":\"<regex>\"}: searches server and tool names.\n4. {\"server\":\"<id>\",\"pattern\":\"<regex>\"}: searches one server.\n5. No arguments: returns the full catalog; use only as a last resort.\n\nIf an MCP call reports an authentication error, call that server's mcp_auth tool with empty arguments when available, then retry the original call only if authentication succeeds.",
"parameters": {
"type": "object",
"properties": {
"pattern": {
"description": "RE2 regex pattern to search server and tool names (max 256 chars). Optionally combine with server to scope the search.",
"type": "string"
},
"server": {
"description": "MCP server identifier to inspect.",
"type": "string"
},
"toolName": {
"description": "Tool name within the server. Requires server to be set.",
"type": "string"
}
}
}
}
},
{
"type": "function",
"function": {
"name": "Glob",
"description": "\nTool to search for files matching a glob pattern\n\n- Works fast with codebases of any size\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files by name patterns\n- You have the capability to call multiple tools in a single response. It is always better to speculatively perform multiple searches that are potentially useful as a batch.\n",
"parameters": {
"type": "object",
"properties": {
"glob_pattern": {
"description": "The glob pattern to match files against.\nPatterns not starting with \"**/\" are automatically prepended with \"**/\" to enable recursive searching.\n\nExamples:\n\t- \"*.js\" (becomes \"**/*.js\") - find all .js files\n\t- \"**/node_modules/**\" - find all node_modules directories\n\t- \"**/test/**/test_*.ts\" - find all test_*.ts files in any test directory",
"type": "string"
},
"target_directory": {
"description": "Absolute path to directory to search for files in. If not provided, defaults to Cursor workspace root.",
"type": "string"
}
},
"required": [
"glob_pattern"
]
}
}
},
{
"type": "function",
"function": {
"name": "Grep",
"description": "A search tool built on ripgrep. Results are capped to several thousand output lines for responsiveness; when truncation occurs, the results report \"at least\" counts, but are otherwise accurate.",
"parameters": {
"type": "object",
"properties": {
"-A": {
"description": "Number of lines to show after each match (rg -A). Requires output_mode: \"content\", ignored otherwise.",
"type": "number"
},
"-B": {
"description": "Number of lines to show before each match (rg -B). Requires output_mode: \"content\", ignored otherwise.",
"type": "number"
},
"-C": {
"description": "Number of lines to show before and after each match (rg -C). Requires output_mode: \"content\", ignored otherwise.",
"type": "number"
},
"-i": {
"description": "Case insensitive search (rg -i) Defaults to false",
"type": "boolean"
},
"glob": {
"description": "Glob pattern to filter files (e.g. \"*.js\", \"*.{ts,tsx}\") - maps to rg --glob",
"type": "string"
},
"head_limit": {
"description": "Limit output size. For \"content\" mode: limits total matches shown. For \"files_with_matches\" and \"count\" modes: limits number of files.",
"minimum": 0,
"type": "number"
},
"multiline": {
"description": "Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false.",
"type": "boolean"
},
"offset": {
"description": "Skip first N entries. For \"content\" mode: skips first N matches. For \"files_with_matches\" and \"count\" modes: skips first N files. Use with head_limit for pagination.",
"minimum": 0,
"type": "number"
},
"output_mode": {
"description": "Output mode: \"content\" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), \"files_with_matches\" shows file paths (supports head_limit), \"count\" shows match counts (supports head_limit). Defaults to \"content\".",
"enum": [
"content",
"files_with_matches",
"count"
],
"type": "string"
},
"path": {
"description": "File or directory to search in (rg pattern -- PATH). Defaults to Cursor workspace root.",
"type": "string"
},
"pattern": {
"description": "The regular expression pattern to search for in file contents",
"type": "string"
},
"type": {
"description": "File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types.",
"type": "string"
}
},
"required": [
"pattern"
]
}
}
},
{
"type": "function",
"function": {
"name": "Read",
"description": "Reads a file from the local filesystem. This tool can also read image files when called with the appropriate path. Formats supported: jpeg/jpg, png, gif, webp.",
"parameters": {
"type": "object",
"properties": {
"limit": {
"description": "The number of lines to read. Only provide if the file is too large to read at once.",
"type": "integer"
},
"offset": {
"description": "The line number to start reading from. Positive values are 1-indexed from the start of the file. Negative values count backwards from the end (e.g. -1 is the last line). Only provide if the file is too large to read at once.",
"type": "integer"
},
"path": {
"description": "The absolute path of the file to read.",
"type": "string"
}
},
"required": [
"path"
]
}
}
},
{
"type": "function",
"function": {
"name": "ReadLints",
"description": "Read and display linter errors from the current workspace. You can provide paths to specific files or directories, or omit the argument to get diagnostics for all files.",
"parameters": {
"type": "object",
"properties": {
"paths": {
"description": "Optional. An array of paths to files or directories to read linter errors for. You can use either relative paths in the workspace or absolute paths. If provided, returns diagnostics for the specified files/directories only. If not provided, returns diagnostics for all files in the workspace.",
"items": {
"type": "string"
},
"type": "array"
}
}
}
}
},
{
"type": "function",
"function": {
"name": "Shell",
"description": "Executes a given command in a shell session with optional foreground timeout.\n\nIMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files, sleeping) - use the specialized tools for this instead.\n\nYou can monitor commands by configuring `notify_on_output`. You will be notified at the end of your turn whenever stdout/stderr output matches the regex `pattern`. Output redirected only to a file will not trigger it. Configure a 5-or-fewer-word `reason` explaining what you are watching for, and optionally configure `debounce_ms`.\n\n<sandboxing>\nBy default, your commands will run in a sandbox. The sandbox allows most writes to the workspace and reads to the rest of the filesystem. Some other syscalls are also disallowed like access to USB devices.\n\nThe sandbox includes network access for common package managers and version control providers (e.g. npm, pypi, crates.io, Maven Central, GitHub, etc.). Standard operations like package installs and fetching dependencies will work without requesting additional permissions.\n\nFor broader network access beyond the allowed domains, you may still need to request 'full_network' permissions.\n\nThe required_permissions argument is used to request additional permissions. If you know you will need a permission, request it. Requesting permissions will slow down the command execution as it will ask the user for approval. Do not hesitate to request permissions if you are certain you need them. For commands you know will need unrestricted network access, request the full_network permission rather than waiting for the command to fail and asking for it later.\n\nThe following permissions are supported:\n\n- full_network: Grants unrestricted network access. This is useful for any commands that need to contact the outside internet, outside of the allowed domains.\n- all: Disables the sandbox entirely. If all is requested the command will run outside of the sandbox.\n\nIf you think a command failed due to sandbox restrictions, run the command again with the required_permissions argument to request what you need.\n</sandboxing>",
"parameters": {
"type": "object",
"properties": {
"block_until_ms": {
"description": "How long to block and wait for the command to complete before moving it to background (in milliseconds). Defaults to 30000ms (30 seconds). Set to 0 to immediately run the command in the background. For a long-lived process, keep the command itself in the foreground and use `block_until_ms: 0`; do not combine it with `nohup`, `&`, `disown`, or another self-backgrounding wrapper, because Cursor must manage the real process. Make sure to set `block_until_ms` to higher than the command's expected runtime. Add some buffer since block_until_ms includes shell startup time; increase buffer next time based on previous elapsed times if you chose too low. E.g. if you sleep for 40s, recommended `block_until_ms` is 45s. Do not specify a 'timeout' parameter; no such param exists.",
"type": "number"
},
"command": {
"description": "The command to execute",
"type": "string"
},
"description": {
"description": "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'",
"type": "string"
},
"notify_on_output": {
"description": "Optional output notification config. Each terminal output which matches the pattern will notify you. ONLY set this when the user explicitly requests monitoring.",
"properties": {
"debounce_ms": {
"description": "Milliseconds that must elapse between notifications. The harness enforces a minimum of 5000ms.",
"type": "number"
},
"pattern": {
"description": "Regex pattern matched against stdout/stderr output. Output redirected only to a file will not trigger it. Do not match all outputs.",
"type": "string"
},
"reason": {
"description": "5 or less words describing why you are watching for this output. The UI (only visible to user) will prefix it as 'Monitored `reason`'.",
"type": "string"
}
},
"required": [
"pattern",
"reason"
],
"type": "object"
},
"request_smart_mode_approval": {
"description": "Set to true when immediately retrying the exact same command after Auto-review blocks it and you decide the user should approve it through the native approval card.",
"type": "boolean"
},
"smart_mode_block_reason": {
"description": "Provide the exact block reason returned by Auto-review in the prior rejection. Required when request_smart_mode_approval is true so the approval card shows the original classifier reason without re-running the classifier.",
"type": "string"
},
"working_directory": {
"description": "The absolute path to the working directory to execute the command in (defaults to current directory)",
"type": "string"
},
"required_permissions": {
"description": "Optional list of permissions to request if the command needs them. Use \"full_network\" for unrestricted network access beyond the sandbox allowlist, or \"all\" to disable the sandbox entirely.",
"type": "array",
"items": {
"type": "string",
"enum": ["full_network", "all"]
}
}
},
"required": [
"command"
]
}
}
},
{
"type": "function",
"function": {
"name": "StrReplace",
"description": "Performs exact string replacements in files.",
"parameters": {
"type": "object",
"properties": {
"new_string": {
"description": "The text to replace it with (must be different from old_string)",
"type": "string"
},
"old_string": {
"description": "The text to replace",
"type": "string"
},
"path": {
"description": "The absolute path to the file to modify",
"type": "string"
},
"replace_all": {
"description": "Replace all occurrences of old_string (default false)",
"type": "boolean"
}
},
"required": [
"path",
"old_string",
"new_string"
]
}
}
},
{
"type": "function",
"function": {
"name": "SwitchMode",
"description": "Switch the interaction mode to better match the current task. Each mode is optimized for a specific type of work.\n\n## When to Switch Modes\n\nSwitch modes proactively when:\n1. **Task type changes** - User shifts from asking questions to requesting implementation, or vice versa\n2. **Complexity emerges** - What seemed simple reveals architectural decisions or multiple approaches\n3. **Debugging needed** - An error, bug, or unexpected behavior requires investigation\n4. **Planning needed** - The task is large, ambiguous, or has significant trade-offs to discuss\n5. **You're stuck** - Multiple attempts without progress suggest a different approach is needed\n\n## When NOT to Switch\n\nDo NOT switch modes for:\n- Simple, clear tasks that can be completed quickly in current mode\n- Mid-implementation when you're making good progress\n- Minor clarifying questions (just ask them)\n- Tasks where the current mode is working well\n\n## Available Modes\n\n### Agent Mode [switchable]\nDefault implementation mode with full access to all tools for making changes.\n\n**Switch to Agent when:**\n- You have a clear understanding of what to implement\n- Planning/debugging is complete and you're ready to code\n- The task is straightforward with an obvious implementation\n- You've gathered enough context and are ready to execute\n\n**Examples:**\n- After planning: \"I've designed the approach, ready to implement\" → Switch to Agent\n- After debugging: \"Found the bug, it's a null check issue\" → Switch to Agent\n- Simple task: User asks to \"Add a comment to this function\" → Stay in Agent (no switch needed)\n\n### Plan Mode [switchable]\nRead-only collaborative mode for designing implementation approaches before coding.\n\n**Switch to Plan when:**\n- The task has multiple valid approaches with significant trade-offs\n- Architectural decisions are needed (e.g., \"Add caching\" - Redis vs in-memory vs file-based)\n- The task touches many files or systems (large refactors, migrations)\n- Requirements are unclear and you need to explore before understanding scope\n- You would otherwise ask multiple clarifying questions\n\n**Examples:**\n- User: \"Add user authentication\" → Switch to Plan (session vs JWT, storage, middleware decisions)\n- User: \"Refactor the database layer\" → Switch to Plan (large scope, architectural impact)\n- User: \"Make the app faster\" → Switch to Plan (need to profile, multiple optimization strategies)\n\n### Debug Mode (cannot switch to this mode)\nSystematic troubleshooting mode for investigating bugs, failures, and unexpected behavior with runtime evidence.\n\n### Ask Mode (cannot switch to this mode)\nRead-only mode for exploring code and answering questions without making changes.\n\n## Important Notes\n\n- **Be proactive**: Don't wait for the user to ask you to switch modes\n- **Explain briefly**: When switching, briefly explain why in your `explanation` parameter\n- **Don't over-switch**: If the current mode is working, stay in it\n- **User approval required**: Mode switches require user consent",
"parameters": {
"type": "object",
"properties": {
"explanation": {
"description": "Optional explanation for why the mode switch is requested. This helps the user understand why you're switching modes.",
"type": "string"
},
"target_mode_id": {
"description": "The mode to switch to. Allowed values: 'plan', 'agent'.",
"type": "string"
}
},
"required": [
"target_mode_id"
]
}
}
},
{
"type": "function",
"function": {
"name": "Task",
"description": "启动一个新代理,自主处理边界清晰且适合委派的任务。\n\nTask 工具会启动专用子代理。每种 subagent_type 都有特定的能力和可用工具。使用 Task 时,必须通过 subagent_type 选择代理类型。\n\n默认行为\n\n默认由当前代理直接处理用户请求,并优先使用 Read、Glob、Grep、Shell、MCP 等直接工具。任务范围较大、步骤较多、需要探索代码库、暂时不确定答案,或者理论上可以并行,都不能单独构成调用 Task 的理由。\n\n只有符合以下至少一种情况时,才可以使用 Task:\n- 用户明确要求启动代理、子代理、worker,或者明确要求并行委派。\n- 存在一项工作量实质、边界清晰、可以独立完成的工作流,将它委派出去能够明显帮助当前任务。\n- 任务确实需要某个专用 subagent_type 才具备的能力。\n\n如果当前代理通过一次或少量直接工具调用就能完成任务,不得使用 Task。不要把整个用户请求交给子代理后直接返回它的结果;当前代理仍然对理解用户意图、整合结果和最终答复负责。\n\n并发规则\n\n- 默认启动一到三个子代理,具体数量应与彼此独立且确有必要委派的工作流数量一致。\n- 只有用户明确要求并行代理,或者确实存在两到三个彼此独立且工作量实质的工作流时,才可以同时启动多个子代理。\n- 单条回复最多启动三个子代理,即使可以构造出更多并行方向也不得超过三个。\n- 不得为了并行而人为拆分同一项调查、同一条执行链或可以由一个代理连续完成的工作。\n- 确需同时启动多个子代理时,在同一条消息中发出多个 Task 调用。\n\n示例\n\n- 用户问“ClientError 类定义在哪里?”:直接使用 Grep 或 Glob,不调用 Task。\n- 用户要求读取一个已知文件:直接使用 Read,不调用 Task。\n- 用户要求在两三个指定文件中搜索代码:直接使用 Read、Grep 或 Glob,不调用 Task。\n- 用户要求通过数据库 API 执行查询:直接调用对应 MCP,不调用 Task。\n- 用户泛泛询问代码库结构:先使用直接工具调查;问题范围广本身不等于必须委派。\n- 用户明确要求“分别启动两个代理独立调查客户端和服务端”:可以同时启动两个边界清晰的 Task。\n\n使用要求\n\n- description 必须是简短、具体、便于用户识别的标题。\n- prompt 必须明确说明子代理要完成的工作、范围、限制和最终应返回的信息。\n- 子代理看不到用户原始消息和父代理此前的步骤,因此 prompt 必须包含完成任务所必需的上下文;但不要复制无关上下文。\n- 子代理返回的内容是供父代理使用的工作结果。父代理应根据任务风险进行必要核对,而不是无条件接受。\n- 子代理类型的描述只说明其能力,不能推翻“默认由当前代理直接处理”的规则。不得仅仅因为某个类型声称可主动使用,就主动调用它。\n- 如果用户明确要求并行运行子代理,仍然必须遵守单条回复最多三个的限制。\n\n恢复与打断\n\n- 使用 resume 并传入已有代理 ID,可以在保留其上下文的情况下继续该代理。\n- 如果目标代理仍在运行,除非 interrupt=true,否则恢复请求会失败。\n- 只有用户明确要求打断或改变正在运行的代理时,才能设置 interrupt=true。\n- resume=\"self\" 表示从当前父代理的完整对话上下文分叉出一个新子代理。\n- 未使用 resume 时,每次 Task 调用都会启动一个全新的代理,因此 prompt 必须自包含。\n\n展示规则\n\n如果在面向用户的答复中提到代理或子代理,必须使用 `[名称](id)` 链接,不得使用 `[agent]`、`[worker]`、`[subagent]` 等泛化标签。云端代理修改代码后,应链接 `[Review](bc-id#changes)`;如果确切知道新增和删除行数,可使用 `[Review +A −D](bc-id#changes)`,并将 A、D 替换为真实数字。只有代理使用了 computer use 时才能使用 `[Try Live](bc-id#desktop)`。\n\n可用的 subagent_type\n\n- generalPurpose:处理已经确定适合委派的、工作量实质且边界清晰的通用任务。仅仅因为搜索结果不确定,不足以调用它。\n- explore:处理已经确定适合委派的、边界清晰且工作量实质的代码库探索。可用于按模式查找文件、搜索关键词或梳理代码结构。调用时应说明调查范围以及所需深度:quick、medium 或 very thorough。\n- shell:专门执行命令、Git 操作及其他终端任务。只有当这本身构成适合独立委派的工作流时才使用。\n- cursor-guide:阅读 Cursor 产品文档,回答 Cursor Desktop、IDE、CLI、Cloud Agents、Bugbot 等产品问题。\n- ci-investigator:调查单个失败的 PR CI 检查,并返回简短的根因总结。\n- bugbot:只有用户明确要求对本地代码改动进行 Bugbot 式审查时才能使用。description 必须严格为 `Bugbot`。除非用户明确要求后台运行,否则 run_in_background=false。prompt 使用固定格式:`Full Repository Path: ...\\nDiff: <branch changes|uncommitted changes|natural language>\\nChange Description: ...\\nCustom Instructions: ...`。默认使用 `Diff: branch changes`。只有常规 diff 无法生成时,才把 natural language 作为最后选择。该类型不支持 resume,每次都启动新代理。\n- security-review:只有用户明确要求安全审查本地代码改动时才能使用。description 必须严格为 `Security Review`。除非用户明确要求后台运行,否则 run_in_background=false。prompt 使用固定格式:`Full Repository Path: ...\\nDiff: <branch changes|uncommitted changes>\\nCustom Instructions: ...`。默认使用 `Diff: branch changes`。该类型不支持 resume,每次都启动新代理。\n- best-of-n-runner:在隔离的 Git worktree 中执行任务,用于用户明确要求的 Best-of-N 并行尝试或隔离实验。\n- test-subagent:仅在该类型自身的具体说明与当前任务明确匹配,并且任务已经满足委派条件时使用。\n\n子代理模型\n\n只有用户明确要求指定子代理模型时,才可以从以下列表选择:\n- inherit\n- claude-opus-5-thinking-high\n- composer-2.5-fast\n- cursor-grok-4.5-low\n- cursor-grok-4.6-high-fast\n- gpt-5.6-sol-medium\n\n用户没有明确指定模型时,使用 inherit。用户请求的模型不在列表中时,不得擅自替换或猜测;应跳过该模型的子代理调用,并告诉用户该模型不可用以及当前可用的模型。面向用户说明所选模型时,除非用户本来就使用 kebab-case 名称,否则不要直接展示 kebab-case slug。\n\n后台代理\n\n后台代理会在当前回复结束后自动发送完成通知。不得使用 AwaitShell 等待、轮询或主动检查 Task 启动的后台代理。可以继续处理其他工作,或者结束当前回复。",
"parameters": {
"type": "object",
"properties": {
"cloud_base_branch": {
"description": "Base branch for the cloud subagent's branch to start from. Default is current branch. Uses remote version of branch; uncommitted or un-pushed branches will fail. Only specify this parameter if environment equals cloud.",
"type": "string"
},
"description": {
"description": "A short, user-friendly title for the subagent. This appears in the UI as the subagent's name. Make it concrete and distinct, consider recent titles to avoid reuse. For resumed subagents which you are prompting to work on a separate task, give an updated description based on the latest work the subagent is performing. (Do not rename if the subagent is continuing work on the same high-level task.)",
"type": "string"
},
"environment": {
"description": "Optional execution environment for the subagent. Use \"local\" (default) for normal local subagents, or \"cloud\" to run the subagent as a cloud agent (i.e. in its own separate worktree). ONLY set to cloud if the user explicitly requests a cloud subagent. DO NOT set to cloud if user does not request cloud. Cloud subagents will work on their own git branch on their own VM. After subagent completion, follow user instructions on whether to merge that branch into your own branch, check it out, or neither. If you mention an agent or subagent in your response, link it with the `[Name](id)` Don't use generic label such as `[agent]`, `[worker]`, or `[subagent]`. For cloud subagents, when the agent has edited code, link to `[Review](bc-id#changes)`, or, if you know the exact added and deleted line counts, `[Review +A −D](bc-id#changes)`, replacing A and D with those counts. Never write A or D literally. Use `[Try Live](bc-id#desktop)` only when the agent used computer use.",
"enum": [
"local",
"cloud"
],
"type": "string"
},
"file_attachments": {
"description": "Optional array of file paths to images or videos to pass to video-review subagents. Files are read and attached to the subagent's context. Use to forward relevant media (e.g. images sent by user) to subagents.",
"items": {
"type": "string"
},
"type": "array"
},
"interrupt": {
"description": "If true and `resume` targets a running async agent, interrupt the current run and send this prompt immediately. Only use when the user explicitly asks to interrupt or change what the running agent is doing.",
"type": "boolean"
},
"model": {
"description": "Optional model slug for this agent. If provided, it must resolve to one of the available model slugs. If omitted, the subagent uses the same model as the parent agent. Do not pass if resume field is set (prior model will be used). Use \"inherit\" unless the user explicitly requested another listed model.",
"type": "string"
},
"prompt": {
"description": "The task for the agent to perform",
"type": "string"
},
"resume": {
"description": "Optional agent ID to resume from. If provided, sends a follow-up message to the agent after it has completed. Requests to a currently running asynchronous agent fail unless `interrupt` is true; set `interrupt` to true only when you intend to interrupt the running agent. Use \"self\" to start a new agent with your own entire conversation history as a starting point (aka 'self-fork').",
"type": "string"
},
"run_in_background": {
"description": "Run the agent in the background (returns output_file path to check later). If this is false, you will be blocked until the agent completes. If the user is currently in Multitask Mode, always set this parameter to True. When true, the background subagent will send a notification when it completes.",
"type": "boolean"
},
"subagent_type": {
"description": "Subagent type to use for this task. Must be one of: generalPurpose, explore, shell, cursor-guide, ci-investigator, bugbot, security-review, best-of-n-runner, test-subagent.",
"enum": [
"generalPurpose",
"explore",
"shell",
"cursor-guide",
"ci-investigator",
"bugbot",
"security-review",
"best-of-n-runner",
"test-subagent"
],
"type": "string"
}
},
"required": [
"description",
"prompt"
]
}
}
},
{
"type": "function",
"function": {
"name": "TodoWrite",
"description": "Use this tool to create and manage a structured task list for your current coding session.",
"parameters": {
"type": "object",
"properties": {
"merge": {
"description": "Whether to merge the todos with the existing todos. If true, the todos will be merged into the existing todos based on the id field. You can leave unchanged properties undefined. If false, the new todos will replace the existing todos.",
"type": "boolean"
},
"todos": {
"description": "Array of TODO items to update or create",
"items": {
"properties": {
"content": {
"description": "The description/content of the TODO item",
"type": "string"
},
"id": {
"description": "Unique identifier for the TODO item",
"type": "string"
},
"status": {
"description": "The current status of the TODO item",
"enum": [
"pending",
"in_progress",
"completed",
"cancelled"
],
"type": "string"
}
},
"required": [
"id",
"content",
"status"
],
"type": "object"
},
"minItems": 2,
"type": "array"
}
},
"required": [
"todos",
"merge"
]
}
}
},
{
"type": "function",
"function": {
"name": "UpdateCurrentStep",
"description": "Record a concise (6 words or less), user-friendly update of the major step or phase you are working on for the parent timeline. Update when the subtask changes. Set `final_summary` and `completed_subtitle` ONCE per response as your last action before the final response. ALWAYS use in parallel with at least one other tool. ALWAYS start the update with a descriptive verb.",
"parameters": {
"properties": {
"completed_subtitle": {
"$ref": "#/properties/current_step",
"description": "4-6 word, past-tense, final summary of the work you have completed. Will be used as your agent subtitle in the UI. Keep the text concise, high-level, and user-friendly. Set this field ONCE per turn, as the last thing you do before your final response, at the same time that you set the final_summary field."
},
"current_step": {
"description": "Major step or phase you are on. Update when the subtask changes. Keep the text concise, high-level, and user-friendly.",
"minLength": 1,
"type": "string"
},
"final_summary": {
"$ref": "#/properties/current_step",
"description": "User-facing executive summary succinctly reporting on your work / responding to the user's message; write this as a concise message speaking back to the user, not as a status tag. Typically 1-3 sentences, or a brief lead-in plus bullet points when there are multiple distinct takeaways, decisions, test results, etc. When using bullets, make them pleasant and easy to scan: 2-5 bullets when possible, one useful idea per bullet, ordered by importance to the user, concise but not cryptic, and no nested bullets unless the user requested detail. Use prose instead of bullets when there is only one main takeaway. Include the most relevant takeaways for the user, as implied by the user's original request. No unnecessary details. When answering questions by the user, include the full answer that the user is seeking. Examples of what to include: full answer(s) to user's question(s), high-level root cause while debugging, status update of completed (or in-progress) work, test results for specifically requested testing, blocking questions the user must answer before you can continue, links to newly created PRs, etc. Examples of what NOT to include (unless implicitly or explicitly requested by the user): tool calls / results, code / log / shell command excerpts, long file paths, line numbers, low-level implementation details, etc. Set this field just ONCE per turn, as the last thing you do before your final response, at the same time that you set the completed_subtitle field."
}
},
"type": "object"
}
}
},
{
"type": "function",
"function": {
"name": "WebFetch",
"description": "Fetch content from a specified URL and return its contents in a readable markdown format. Use this tool when you need to retrieve and analyze web content.",
"parameters": {
"type": "object",
"properties": {
"requestSmartModeApproval": {
"description": "Set to true when immediately retrying the exact same fetch after Auto-review blocks it and you decide the user should approve it through the native approval card.",
"type": "boolean"
},
"smartModeBlockReason": {
"description": "Provide the exact block reason returned by Auto-review in the prior rejection. Required when requestSmartModeApproval is true so the approval card shows the original classifier reason without re-running the classifier.",
"type": "string"
},
"url": {
"description": "The URL to fetch. The content will be converted to a readable markdown format.",
"type": "string"
}
},
"required": [
"url"
]
}
}
},
{
"type": "function",
"function": {
"name": "WebSearch",
"description": "Search web for real-time info on any topic; use for up-to-date facts not in training data, like current events or tech updates. Results include snippets and URLs.",
"parameters": {
"type": "object",
"properties": {
"explanation": {
"description": "One sentence explanation as to why this tool is being used, and how it contributes to the goal.",
"type": "string"
},
"search_term": {
"description": "The search term to look up on the web. Be specific and include relevant keywords for better results. For technical queries, include version numbers or dates if relevant.",
"type": "string"
}
},
"required": [
"search_term"
]
}
}
},
{
"type": "function",
"function": {
"name": "Write",
"description": "Writes a file to the local filesystem.",
"parameters": {
"type": "object",
"properties": {
"contents": {
"description": "The contents to write to the file",
"type": "string"
},
"path": {
"description": "The absolute path to the file to modify",
"type": "string"
}
},
"required": [
"path",
"contents"
]
}
}
}
],
"variants": {}
}