Skip to content

dreadnode.tools

API reference for the dreadnode.tools module.

Provides a stateful, in-memory key-value store for the toolset’s lifetime.

This toolset allows the agent to save, retrieve, and manage data, enabling it to remember information across multiple steps and tool calls.

clear_memory(
key: Annotated[
str | None,
"The specific key to clear. If not provided, all memory is cleared.",
] = None,
) -> str

Clears a specific key from memory, or clears all memory if no key is provided.

list_memory_keys() -> list[str]

Lists all keys currently stored in memory.

retrieve_memory(
key: Annotated[
str, "The key of the value to retrieve."
],
) -> str

Retrieves a value from memory using the specified key.

save_memory(
key: Annotated[
str, "The unique key to store the value under."
],
value: Annotated[
str, "The string value to store in memory."
],
) -> str

Saves a value to memory with the specified key, overwriting any existing value.

ask_user(
question: Annotated[
str, "The question to ask the user"
],
options: Annotated[
list[str] | list[HumanPromptOption] | None,
"Optional list of choices. If provided, user selects from these. If None, user can type free-form response.",
] = None,
*,
kind: Annotated[
Literal["input", "choice", "approval"] | None,
"Prompt kind (input, choice, approval). Defaults based on options.",
] = None,
details: Annotated[
str | None, "Optional supporting details."
] = None,
allow_free_text: Annotated[
bool | None,
"Allow free-form text in choice prompts.",
] = None,
default_option: Annotated[
str | None, "Default option label."
] = None,
severity: Annotated[
str | None, "Optional severity for the prompt."
] = None,
request_id: Annotated[
str | None, "Optional request id override."
] = None,
source_tool_name: Annotated[
str | None, "Source tool name."
] = None,
source_tool_call_id: Annotated[
str | None, "Source tool call id."
] = None,
) -> str

Ask the user a question and wait for their response.

Use this tool when you need:

  • Clarification on ambiguous requirements
  • User preference between options
  • Confirmation before destructive actions
  • Additional information to proceed

Best Practices

  • Ask specific, clear questions
  • Provide options when choices are limited
  • Don’t ask unnecessary questions (use your judgment first)
  • Explain why you’re asking if it’s not obvious

Examples

Free-form question:

ask_user("What authentication method should I use?")

Multiple choice:

ask_user(
"Which database should I configure?",
options=["PostgreSQL", "MySQL", "SQLite"]
)

Confirmation:

ask_user(
"This will delete 15 files. Proceed?",
options=["Yes, delete them", "No, cancel"]
)

Parameters:

  • question (Annotated[str, 'The question to ask the user']) –The question to ask.
  • options (Annotated[list[str] | list[HumanPromptOption] | None, 'Optional list of choices. If provided, user selects from these. If None, user can type free-form response.'], default: None ) –Optional list of choices for the user.

Returns:

  • str –The user’s response as a string.
bash(
cmd: str,
*,
timeout: int = 120,
cwd: str | None = None,
env: dict[str, str] | None = None,
input: str | None = None,
) -> str

Execute a bash command in a subprocess.

Use for shell commands, scripts, or operations requiring shell features.

Parameters:

  • cmd (str) –Bash command to execute.
  • timeout (int, default: 120 ) –Maximum execution time in seconds.
  • cwd (str | None, default: None ) –Working directory for the command.
  • env (dict[str, str] | None, default: None ) –Additional environment variables.
  • input (str | None, default: None ) –Text to send to stdin.

Returns:

  • str –Command output.
confirm(
action: Annotated[
str, "Description of the action to confirm"
],
*,
default_yes: Annotated[
bool, "Whether to default to yes if unclear"
] = False,
) -> bool

Ask user to confirm an action.

Returns True if confirmed, False if rejected.

Parameters:

  • action (Annotated[str, 'Description of the action to confirm']) –What you’re asking to confirm.
  • default_yes (Annotated[bool, 'Whether to default to yes if unclear'], default: False ) –If True, ambiguous responses default to yes.

Returns:

  • bool –True if user confirms, False otherwise.
default_tools() -> dict[str, Tool | Toolset]

All standard tools, keyed by function name.

Imports are deferred to avoid circular dependencies.

delete_lines(
path: Annotated[str, "Path to the file"],
start_line: Annotated[
int, "First line to delete (1-indexed)"
],
end_line: Annotated[
int, "Last line to delete (inclusive)"
],
*,
cwd: Annotated[str | None, "Working directory"] = None,
) -> str

Delete a range of lines from a file.

Line numbers are 1-indexed and inclusive on both ends.

Parameters:

  • path (Annotated[str, 'Path to the file']) –Path to the file.
  • start_line (Annotated[int, 'First line to delete (1-indexed)']) –First line to delete (1-indexed).
  • end_line (Annotated[int, 'Last line to delete (inclusive)']) –Last line to delete (1-indexed, inclusive).
  • cwd (Annotated[str | None, 'Working directory'], default: None ) –Working directory for relative paths.

Returns:

  • str –Success message with deleted line count.
edit_file(
path: Annotated[str, "Path to the file to edit"],
old_string: Annotated[
str, "Text to replace (fuzzy matching supported)"
],
new_string: Annotated[str, "Replacement text"],
*,
replace_all: Annotated[
bool, "Replace all occurrences"
] = False,
cwd: Annotated[
str | None,
"Working directory (defaults to current)",
] = None,
) -> str

Perform surgical text replacement in a file with fuzzy matching.

You MUST use the read tool at least once before editing a file to understand the exact content. Preserve the exact indentation (tabs/spaces) as it appears in the file.

  • The edit will FAIL if old_string is not found in the file.
  • The edit will FAIL if old_string matches multiple locations. Provide more surrounding context to make the match unique, or use replace_all=True to change every occurrence.
  • For multiple edits to the same file, prefer multiedit.
  • Use replace_all=True for renaming variables/functions across the file.

Parameters:

  • path (Annotated[str, 'Path to the file to edit']) –Path to the file to edit.
  • old_string (Annotated[str, 'Text to replace (fuzzy matching supported)']) –Text to find (fuzzy matching supported).
  • new_string (Annotated[str, 'Replacement text']) –Replacement text.
  • replace_all (Annotated[bool, 'Replace all occurrences'], default: False ) –Replace all occurrences. Default: False.
  • cwd (Annotated[str | None, 'Working directory (defaults to current)'], default: None ) –Working directory for relative paths.

Returns:

  • str –Success message with edit details.
insert_lines(
path: Annotated[str, "Path to the file"],
line_number: Annotated[
int, "Line number to insert at (1-indexed)"
],
content: Annotated[str, "Content to insert"],
*,
cwd: Annotated[str | None, "Working directory"] = None,
) -> str

Insert content at a specific line number.

Line numbers are 1-indexed. Content is inserted BEFORE the specified line. Use line_number=1 to insert at the beginning. Use a line number past the end to append.

Parameters:

  • path (Annotated[str, 'Path to the file']) –Path to the file.
  • line_number (Annotated[int, 'Line number to insert at (1-indexed)']) –Line to insert before (1-indexed).
  • content (Annotated[str, 'Content to insert']) –Content to insert.
  • cwd (Annotated[str | None, 'Working directory'], default: None ) –Working directory for relative paths.

Returns:

  • str –Success message.
multiedit(
path: Annotated[str, "Path to the file to edit"],
edits: Annotated[
list[dict[str, Any]],
"Array of edits: [{old_string, new_string, replace_all?}, ...]",
],
*,
cwd: Annotated[
str | None,
"Working directory (defaults to current)",
] = None,
) -> str

Apply multiple edits to a single file in one operation.

Prefer this tool over edit_file when you need to make multiple changes to the same file. Each edit in the array should have:

  • old_string: text to find (must match file contents)
  • new_string: replacement text
  • replace_all (optional): replace all occurrences

All edits are applied in sequence — each edit operates on the result of the previous one. All edits must succeed or none are applied. Since edits are sequential, ensure earlier edits don’t affect the text that later edits are trying to find.

Parameters:

  • path (Annotated[str, 'Path to the file to edit']) –Path to the file.
  • edits (Annotated[list[dict[str, Any]], 'Array of edits: [{old_string, new_string, replace_all?}, ...]']) –List of edit operations.
  • cwd (Annotated[str | None, 'Working directory (defaults to current)'], default: None ) –Working directory for relative paths.

Returns:

  • str –Summary of all edits applied.
python(
code: str,
*,
timeout: int = 120,
cwd: str | None = None,
env: dict[str, str] | None = None,
) -> str

Execute Python code in a subprocess.

Use for custom logic, data processing, or operations not covered by other tools. Results must be printed to stdout to be captured.

Parameters:

  • code (str) –Python code to execute.
  • timeout (int, default: 120 ) –Maximum execution time in seconds.
  • cwd (str | None, default: None ) –Working directory for the command.
  • env (dict[str, str] | None, default: None ) –Additional environment variables.

Returns:

  • str –Python process output.