Tools Module¶
Tools module for atloop agent.
- class atloop.tools.ToolResult(ok: bool, stdout: str, stderr: str, meta: Dict[str, Any])[source]¶
Bases:
objectResult of tool execution.
BaseTool¶
ToolRegistry¶
- class atloop.tools.registry.ToolRegistry(sandbox: SandboxAdapter, skill_loader=None)[source]¶
Bases:
objectRegistry for managing tools.
- __init__(sandbox: SandboxAdapter, skill_loader=None)[source]¶
Initialize tool registry.
- Parameters:
sandbox – Sandbox adapter instance (required by run, read_file, write_file, etc.)
skill_loader – Optional skill loader for read_skill_file and skill tools. Passed automatically to tools that declare skill_loader in __init__.
- get_registration_stats() Dict[str, Any][source]¶
Get tool registration statistics.
- Returns:
Dictionary with registration stats (discovered, registered, failed, tools)
- execute(tool_name: str, args: Dict[str, Any]) ToolResult[source]¶
Execute a tool.
- Parameters:
tool_name – Name of the tool
args – Tool arguments
- Returns:
ToolResult instance
- Raises:
ValueError – If tool not found
ToolExecutor¶
- class atloop.orchestrator.executor.tool_executor.ToolExecutor(coordinator: WorkflowCoordinator)[source]¶
Bases:
objectTool executor for executing tool calls.
- __init__(coordinator: WorkflowCoordinator)[source]¶
Initialize tool executor.
- Parameters:
coordinator – Workflow coordinator instance
Filesystem Tools¶
Filesystem tools.
- class atloop.tools.filesystem.ReadFileTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for reading files from the sandbox workspace with type detection and chunked reading.
Features: - Automatic file type detection (text/binary) - Support for large files via line range reading - Binary file detection and handling - File size limits (10MB max for full read)
Use cases: - Reading source code files - Reading configuration files - Reading documentation files - Reading log files (with line ranges)
Note: This tool reads from the sandbox workspace (/workspace), not from the local machine. For reading skill files (stored locally), use read_skill_file instead.
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize read file tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute read file tool.
- Args:
- args: Tool arguments dictionary
path (str, required): File path. Relative paths are relative to /workspace. Absolute paths are used as-is.
offset (int, optional): Start line number (1-indexed). Default: 1 (start of file). Use this for reading large files in chunks.
limit (int, optional): Number of lines to read. If not specified, reads from offset to end of file. Use this for reading large files in chunks.
- Returns:
ToolResult with: - ok (bool): True if file was read successfully (no errors in stderr) - stdout (str): File content (or metadata for binary/large files) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains path, file_type, file_size, start_line, end_line
- Examples:
# Read entire file read_file(path=”src/main.py”)
# Read first 100 lines read_file(path=”src/main.py”, offset=1, limit=100)
# Read lines 50-100 read_file(path=”src/main.py”, offset=50, limit=51)
# Read from line 200 to end read_file(path=”src/main.py”, offset=200)
Behavior: - Text files: Returns file content in stdout - Binary files: Returns metadata message (file type, size) instead of content - Large files (>10MB): Returns metadata message, suggests using line ranges - File not found: Returns ok=False with error message in stderr - Line ranges: If offset/limit specified, only reads those lines
Path Handling: - All commands run with workdir=”/workspace” - Relative paths are resolved relative to /workspace - Absolute paths are used as-is
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False
- class atloop.tools.filesystem.ReadSkillFileTool(skill_loader=None)[source]¶
Bases:
BaseToolTool for reading files from skill directories (on local machine, not from sandbox workspace).
🚨🚨🚨 CRITICAL: This tool reads from skill directories on the LOCAL machine, NOT from the sandbox!
Key Points: - Skill files are stored LOCALLY (on the host machine, in ~/.atloop/skills/ or project .atloop/skills/) - Workspace is a REMOTE SANDBOX (/workspace) - it does NOT contain skill files or templates - When a skill mentions other files (e.g., “see docx-js.md”, “reference guide.md”), those files are LOCAL - You MUST use `read_skill_file` to read skill-related files - they are NOT in the sandbox! - DO NOT try to use `read_file` or `run(“cat …”)` to find skill files in the sandbox - they don’t exist there!
Use cases: - Reading skill files (when skill mentions other files to reference) - Reading files referenced in skill documentation - Accessing skill-specific resources (templates, guides, examples)
Path resolution: - With skill_name: Path is relative to skill directory (most common use case) - Without skill_name: Absolute path or relative to ~/.atloop/ - Supports ~ expansion for home directory
Important distinction: - ✅ Skill files → Use read_skill_file (stored locally) - ✅ Workspace files → Use read_file (stored in remote sandbox /workspace) - ❌ Never use `read_file` or `run` to find skill files - they are not in the sandbox!
- __init__(skill_loader=None)[source]¶
Initialize read skill file tool.
- Parameters:
skill_loader – Optional skill loader instance for resolving skill paths
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute read skill file tool.
🚨🚨🚨 CRITICAL: This tool reads from skill directories on the LOCAL machine, NOT from the sandbox workspace!
Important understanding: - Skill files are stored LOCALLY (on the host machine) - Workspace is a REMOTE SANDBOX (/workspace) - it does NOT contain skill files - When a skill mentions other files, those files are LOCAL, not in the sandbox - You MUST use `read_skill_file` to read skill-related files - DO NOT try to use `read_file` or `run(“cat …”)` to find skill files in the sandbox - they don’t exist there!
Use read_file to read files from the sandbox workspace (/workspace).
- Args:
- args: Tool arguments dictionary
path (str, required): File path. Resolution depends on skill_name: - If skill_name provided: Path is relative to skill directory - If path starts with ~: Expanded to home directory - If absolute path: Used as-is - Otherwise: Relative to ~/.atloop/
skill_name (str, optional): Skill name. If provided, path is resolved relative to the skill’s directory. Use this when a skill mentions other files to reference.
offset (int, optional): Start line number (1-indexed). Default: 1. Use for reading large files in chunks.
limit (int, optional): Number of lines to read. If not specified, reads from offset to end of file.
- Returns:
ToolResult with: - ok (bool): True if file was read successfully (no errors in stderr) - stdout (str): File content (or metadata for binary/large files) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains path, file_size, start_line, end_line
- Examples:
# Read skill file (when skill mentions other files) read_skill_file(path=”references/guide.md”, skill_name=”long_document_writer”)
# Read skill documentation read_skill_file(path=”docx-js.md”, skill_name=”docx”)
# Read with line range read_skill_file(path=”skill-doc.md”, skill_name=”docx”, offset=1, limit=50)
When to use this vs read_file: - ✅ Reading skill files → use read_skill_file (stored locally, NOT in sandbox) - ✅ Reading files referenced in skills → use read_skill_file (skill mentions are LOCAL files) - ✅ Reading skill templates/examples → use read_skill_file (stored locally) - ❌ Reading workspace files → use read_file (sandbox files in /workspace) - ❌ DO NOT use `read_file` or `run` to find skill files - they are NOT in the sandbox!
File Size Limits: - Files larger than 10MB return metadata only - Use offset/limit to read specific sections of large files
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False
- class atloop.tools.filesystem.WriteFileTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for writing files (creates new files or completely overwrites existing files).
⚠️ Important Usage Guidelines: - Use for: Creating new files or completely rewriting existing files - Do NOT use for: Modifying parts of existing files (use edit_file instead) - Character limit: Maximum 6,000 characters per turn - Directory creation: Automatically creates parent directories if they don’t exist
When to use write_file vs edit_file: - ✅ Creating a new file → use write_file - ✅ Completely rewriting a file → use write_file - ❌ Modifying a function/class → use edit_file (more precise and safer) - ❌ Adding/removing a few lines → use edit_file (more precise and safer)
File content handling: - Uses placeholder mechanism: content should be FILE_CONTENT_#1, FILE_CONTENT_#2, etc. - Actual content follows the JSON output, delimited by —(FILE_CONTENT_#1)— - This prevents JSON parsing issues with large content
Trailing newline behavior: - Files always end with exactly one newline character - Input content’s trailing newline is normalized automatically
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize write file tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute write file tool.
⚠️ WARNING: This tool completely overwrites the entire file. If the file exists, all existing content will be replaced with the new content.
When to use this tool: - ✅ Creating a new file - ✅ Completely rewriting an existing file - ❌ Modifying part of a file → use edit_file instead - ❌ Appending content → use append_file instead
- Args:
- args: Tool arguments dictionary
path (str, required): File path. Relative paths are relative to /workspace. Parent directories are automatically created if they don’t exist.
content (str, required): File content to write. This will completely replace any existing file content. Maximum 6,000 characters per turn. Use placeholder FILE_CONTENT_#1 in JSON, actual content follows after.
- Returns:
ToolResult with: - ok (bool): True if file was written successfully (no errors in stderr) - stdout (str): Command output (usually empty) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains path, cmd, duration_ms
- Examples:
# Create a new Python file write_file(path=”src/main.py”, content=”FILE_CONTENT_#1”) # Then provide actual content after JSON: # —(FILE_CONTENT_#1)— # def main(): # print(“Hello, World!”) # —(FILE_CONTENT_#1)—
Note on Trailing Newlines: This tool uses heredoc (cat > file <<’FILE_EOF’) which automatically adds a trailing newline. The tool normalizes input to ensure files always end with exactly one newline: - If content ends with ‘n’, it’s removed before writing (heredoc adds one) - If content doesn’t end with ‘n’, heredoc adds one - Result: File always ends with exactly one newline character - Exception: Empty string content results in a file with one newline
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False
- class atloop.tools.filesystem.AppendFileTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for appending content to the end of existing files.
⚠️ This tool is fully available and can be used normally!
Use cases: - Continuing to write files that exceed 6,000 characters (after initial write_file) - Adding log entries - Appending comments or notes - Building files incrementally
Key differences from write_file and edit_file: - write_file: Completely overwrites file (creates or replaces entire file) - edit_file: Replaces specific text within file (precise modifications) - append_file: Adds content to end of file (doesn’t modify existing content)
Content handling: - Content is appended exactly as provided - Preserves trailing newlines in input content - Unlike write_file/edit_file, doesn’t normalize trailing newlines
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize append file tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute append file tool.
⚠️ IMPORTANT: This tool is fully available and can be used normally! Don’t assume it’s unavailable - it works perfectly fine.
- Args:
- args: Tool arguments dictionary
path (str, required): File path. Relative paths are relative to /workspace. File must exist (this tool appends to existing files, doesn’t create new ones).
content (str, required): Content to append to the end of the file.
- Returns:
ToolResult with: - ok (bool): True if content was appended successfully (no errors in stderr) - stdout (str): Command output (usually empty) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains path, cmd, duration_ms
- Examples:
# Continue writing a long document (after initial write_file with 6k chars) append_file(
path=”long_document.md”, content=”nn## Chapter 2nThis is the continuation…”
)
# Add a log entry append_file(
path=”app.log”, content=”[2024-01-01] User logged inn”
)
Content Appending Behavior: - Content is appended exactly as provided, without modification - If content ends with ‘n’, it’s appended with the newline - If content doesn’t end with ‘n’, it’s appended without a newline - This differs from write_file and edit_file, which normalize trailing newlines - Use this when you need precise control over trailing newlines
Common Workflow: 1. First turn: Use write_file to create file with first 6k characters 2. Subsequent turns: Use append_file to continue adding content 3. Check file: Use read_file to verify complete content
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False
- class atloop.tools.filesystem.EditFileTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for editing files using Git-style diff (old_string -> new_string).
⚠️ This is the preferred tool for modifying existing files!
Why use edit_file instead of write_file: - ✅ More precise: Only modifies the specified part - ✅ Safer: Doesn’t risk overwriting unrelated code - ✅ More efficient: No need to read and rewrite entire file - ✅ Better for local modifications: Functions, classes, paragraphs, etc.
Safety features: - Match count validation: Only replaces if old_string appears exactly once - Prevents accidental multiple replacements - Clear error messages when matches are not found or ambiguous
Use cases: - Modifying a function or method - Updating a class definition - Changing a specific section of code - Fixing a bug in a specific location - Updating configuration values
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize edit file tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute edit file tool.
⚠️ IMPORTANT: This is the preferred tool for modifying existing files! Use this instead of write_file for any file modifications.
- Args:
- args: Tool arguments dictionary
path (str, required): File path. Relative paths are relative to /workspace.
content (str, required): Content in format <old>old_string</old><new>new_string</new>. The old_string is the exact text to replace. Must match exactly including whitespace, indentation, and newlines. Should include at least 3 lines of context before and after to ensure uniqueness.
replace_all (bool, optional): If True, replace all occurrences of old_string. Default: False. When False, only replaces if old_string appears exactly once.
- Returns:
ToolResult with: - ok (bool): True if edit was successful (no errors in stderr) - stdout (str): Diff summary (e.g., “Updated file: +2 lines, -1 lines”) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains path, operation, replace_all
- Examples:
# Modify a function edit_file(
path=”src/utils.py”, content=”<old>def calculate(x, y):
return x + y</old><new>def calculate(x, y): return x * y</new>”
)
# Add context for uniqueness edit_file(
path=”src/main.py”, content=”<old># Configuration
DEBUG = True # End config</old><new># Configuration DEBUG = False # End config</new>”
)
Safety Checks: - Match count validation: When replace_all=False (default):
If old_string appears 0 times → Error: “old_string not found”
If old_string appears 1 time → Success: Replaces it
If old_string appears 2+ times → Error: “found X times, make old_string more specific”
When replace_all=True: Replaces all occurrences without validation
Best Practices: 1. Include context: Add at least 3 lines before and after the code you’re changing 2. Be precise: Match exact whitespace, indentation, and newlines 3. Make it unique: Ensure old_string appears only once in the file 4. Use read_file first: Read the file to see exact formatting before editing
Error Messages: - “old_string not found” → Check that old_string exactly matches file content - “found X times” → Add more context to make old_string unique, or use replace_all=True - “File not found” → File doesn’t exist
Note on Trailing Newlines: Files always end with exactly one newline character after editing, regardless of whether new_string ends with a newline or not.
- class atloop.tools.filesystem.MultiEditFileTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for editing multiple files in a single atomic transaction.
Key Features: - Transactional: All edits succeed or all fail (atomicity) - Batch operations: Edit multiple files in one operation - Rollback on error: If any edit fails, all changes are rolled back
Use cases: - Updating imports across multiple files - Refactoring code that spans multiple files - Applying the same change to multiple files - Coordinated updates that must happen together
When to use: - ✅ Need to edit multiple files atomically - ✅ Changes must all succeed or all fail - ❌ Single file edit → use edit_file (simpler) - ❌ Independent edits → use multiple edit_file calls
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize multi-edit file tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute multi-edit file tool.
⚠️ Transactional Behavior: All edits are atomic - either all succeed or all fail. If any edit fails, all changes are rolled back and no files are modified.
- Args:
- args: Tool arguments dictionary
- edits (list, required): List of edit operations. Each edit is a dictionary with:
path (str, required): File path. Relative paths are relative to /workspace.
old_string (str, required): Exact text to replace. Must match exactly. If empty, creates a new file.
new_string (str, required): Replacement text.
replace_all (bool, optional): Replace all occurrences. Default: False.
- Returns:
ToolResult with: - ok (bool): True if all edits succeeded (no errors in stderr) - stdout (str): Summary of edited files (e.g., “Successfully edited 3 file(s)”) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains successful_edits, failed_edits, total_edits, edited_files
- Examples:
# Update imports in multiple files atomically multi_edit_file(edits=[
- {
“path”: “src/file1.py”, “old_string”: “from utils import helper”, “new_string”: “from utils.helpers import helper”
}, {
“path”: “src/file2.py”, “old_string”: “from utils import helper”, “new_string”: “from utils.helpers import helper”
}
])
Transaction Phases: 1. Validation phase: Read all files, check they exist 2. Transaction phase: Apply all edits in memory 3. Commit phase: Write all files (only if all edits succeeded)
Error Handling: - If any file read fails → All edits rolled back, error in stderr - If any edit fails (old_string not found) → All edits rolled back, error in stderr - If any file write fails → Partial success reported, failed files in stderr - Success is determined by stderr content, not exit code
Best Practices: 1. Use when edits must be atomic (all or nothing) 2. Ensure all old_string values are unique in their respective files 3. Include sufficient context in old_string for uniqueness 4. Test with single-file edits first, then combine into multi-edit
Note on Trailing Newlines: All files will always end with exactly one newline character after editing.
- class atloop.tools.filesystem.GlobFilesTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for finding files using gitignore-style glob patterns.
Features: - Supports common glob patterns (, *) - Recursive directory searching - File filtering by extension or pattern
Use cases: - Finding all Python files: *.py - Finding all test files: test_*.py - Finding files recursively: **/*.js - Listing files in a directory: dir/*.txt
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize glob files tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute glob tool to find files matching a pattern.
- Args:
- args: Tool arguments dictionary
pattern (str, required): Glob pattern to match files. Supports: - *.py: Matches all .py files in current directory - **/*.py: Matches all .py files recursively - test_*.py: Matches files starting with “test_” - dir/*.txt: Matches .txt files in “dir” directory
max_results (int, optional): Maximum number of results to return. Default: 100. Use this to limit output for very large matches.
- Returns:
ToolResult with: - ok (bool): True if pattern was executed successfully (no errors in stderr) - stdout (str): Formatted list of matched files, one per line - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains pattern, max_results, matched_count, matched_files
- Examples:
# Find all Python files glob(pattern=”*.py”)
# Find all Python files recursively glob(pattern=”**/*.py”)
# Find test files glob(pattern=”test_*.py”)
# Find files in specific directory glob(pattern=”src/*.py”)
# Limit results glob(pattern=”*.py”, max_results=10)
Pattern Support: - *: Matches any characters (except path separator) - **: Matches any characters including path separators (recursive) - Directory patterns: dir/*.ext matches files in “dir” directory - Leading ./ is optional and ignored
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Empty results (no matches) is considered success (ok=True) - Check stderr for specific error messages if ok=False
System Tools¶
System tools.
- class atloop.tools.system.RunCommandTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for executing shell commands in the sandbox workspace.
⚠️ This is the primary tool for executing system commands!
Use cases: - Running build commands (make, npm, pip, etc.) - Running tests (pytest, unittest, etc.) - Executing scripts (python3, node, etc.) - File operations (ls, cat, grep, find, etc.) - System checks (which, type, etc.)
Important notes: - Commands run in /workspace directory - Success is determined by stderr content, NOT exit code - Many commands return exit_code=0 even with errors - Always check stdout and stderr content to judge success
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize run command tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute shell command in the sandbox workspace.
⚠️ IMPORTANT: This is the primary tool for executing system commands! Use this instead of trying to execute commands through other means.
- Args:
- args: Tool arguments dictionary
cmd (str, required): Shell command to execute. Can be any valid shell command. Examples: “ls -la”, “python3 script.py”, “grep -rn ‘pattern’ .”, etc.
timeout_sec (int, optional): Timeout in seconds. Default: 600 (10 minutes). Use shorter timeouts for quick commands, longer for builds/tests.
- Returns:
ToolResult with: - ok (bool): True if command succeeded (no errors in stderr) - stdout (str): Standard output from the command - stderr (str): Standard error from the command (empty string means success) - meta (dict): Contains cmd, duration_ms
- Examples:
# List files run(cmd=”ls -la”)
# Run Python script run(cmd=”python3 script.py”)
# Run tests run(cmd=”pytest tests/”)
# Search for pattern run(cmd=”grep -rn ‘def function’ .”)
# View file content run(cmd=”cat file.py”) run(cmd=”head -n 50 file.py”) run(cmd=”tail -n 20 file.py”)
⚠️ Critical: Success Determination - DO NOT rely on exit_code - it’s unreliable! - Success = empty stderr (no error messages) - Failure = non-empty stderr (contains error messages) - Many commands return exit_code=0 even with errors (e.g., pytest collection errors) - Always read stdout and stderr content to judge success
Common Commands: - File viewing: cat, head, tail, less, more - File search: grep, find, locate - Text processing: sed, awk, cut, sort, uniq - File operations: ls, pwd, cd, mkdir, rm, cp, mv - Python: python3 (not python), pip3 (not pip) - Other: echo, wc, diff, which, type
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the command succeeded - If stderr contains “error”, “failed”, “exception”, etc., command likely failed - Always check stderr content, not just ok field
Search Tools¶
Search tools.
- class atloop.tools.search.SearchTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolEnhanced tool for searching file contents using grep with regex, context lines, and file filtering.
Features: - Full regex pattern support - Context lines (before/after matches) - File filtering by glob pattern - Multiple output modes (content, files, count) - Case-insensitive search option
Use cases: - Finding function definitions: search(‘def function_name’) - Finding imports: search(‘^import |^from ‘) - Finding specific patterns: search(‘TODO|FIXME’) - Searching in specific file types: search(‘pattern’, glob=’*.py’)
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize search tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute enhanced search tool to find patterns in files.
- Args:
- args: Tool arguments dictionary
query (str, required): Search query as regex pattern. Supports full regex syntax. Examples: “def function”, “^import “, “TODO|FIXME”, “class w+”
glob (str, optional): Glob pattern to filter files. Examples: “.py”, “*/*.js”
output_mode (str, optional): Output mode. Default: “content” - “content”: Show matching lines with context (default) - “files_with_matches”: Show only file paths that contain matches - “count”: Show match count per file
-A (int, optional): Number of lines to show after each match
-B (int, optional): Number of lines to show before each match
-C (int, optional): Number of lines to show before and after each match
-i (bool, optional): Case-insensitive search. Default: False
-n (bool, optional): Show line numbers. Default: True
max_results (int, optional): Maximum number of results to return. Default: 50. Limits output for very large result sets.
- Returns:
ToolResult with: - ok (bool): True if search executed successfully (no errors in stderr) - stdout (str): Search results (matching lines, file paths, or counts) - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains query, glob, output_mode, max_results, cmd
- Examples:
# Find function definitions search(query=”def w+”, glob=”*.py”)
# Find imports with context search(query=”^import |^from “, glob=”*.py”, -C=2)
# Find TODO comments (case-insensitive) search(query=”TODO|FIXME”, -i=True)
# Find files containing pattern (without showing content) search(query=”def main”, output_mode=”files_with_matches”)
# Count matches per file search(query=”class w+”, output_mode=”count”)
Regex Pattern Tips: - Use ^ for start of line: ^def matches “def” at line start - Use $ for end of line: import$ matches “import” at line end - Use | for alternation: TODO|FIXME matches either - Use w+ for word characters: def w+ matches “def function_name” - Escape special chars: . matches literal dot
Context Lines: - Use -C=3 to show 3 lines before and after each match - Use -B=5 to show 5 lines before each match - Use -A=2 to show 2 lines after each match - Context helps understand code structure around matches
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the search succeeded - No matches found is considered success (ok=True, empty stdout) - Check stderr for specific error messages if ok=False
Interaction Tools¶
Interaction tools module.
- class atloop.tools.interaction.SkillTool(skill_loader=None)[source]¶
Bases:
BaseToolTool for loading skill content on-demand.
When the LLM needs guidance from a skill (e.g., tool-usage, error-handling), it uses this tool to load the full skill content. The skill content is returned as stdout for the LLM to read and apply.
Use cases: - Loading tool usage best practices (tool-usage skill) - Loading error handling guidance (error-handling skill) - Loading domain-specific knowledge (any custom skill)
Note: This tool requires skill_loader to be configured in the ToolRegistry.
- __init__(skill_loader=None)[source]¶
Initialize skill tool.
- Parameters:
skill_loader – SkillLoader or EnhancedSkillLoader instance for loading skill content
- class atloop.tools.interaction.TodoReadTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for reading and displaying the current task list from TODO.md.
Use cases: - Checking current task status - Reviewing progress on multi-step tasks - Understanding what work is in progress - Planning next steps based on current status
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize todo read tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute todo read tool to read and display TODO.md.
- Args:
args: Tool arguments dictionary (no arguments required)
- Returns:
ToolResult with: - ok (bool): True if TODO.md was read successfully (no errors in stderr) - stdout (str): Formatted TODO list with tasks grouped by status - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains todo_file, todo_count, pending, in_progress, completed
- Examples:
# Read current TODO list todo_read()
Output Format: Tasks are grouped by status and displayed as: ``` # TODO List (3 task(s))
## In Progress 1. Task 1 (Running task 1)
## Pending 1. Task 2 (Will run task 2)
## Completed (1) 1. Task 3
Summary: 1 pending, 1 in progress, 1 completed ```
Behavior: - If TODO.md doesn’t exist: Returns ok=True with message to use todo_write - If TODO.md exists but is empty: Returns ok=True with message - If TODO.md has tasks: Returns formatted list grouped by status - Only shows first 5 completed tasks (to avoid clutter)
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False
- class atloop.tools.interaction.TodoWriteTool(sandbox: SandboxAdapter)[source]¶
Bases:
BaseToolTool for creating and managing task lists in TODO.md format.
Use cases: - Tracking progress on complex, multi-step tasks - Managing task status (pending, in_progress, completed) - Organizing work into manageable chunks - Providing visibility into current work status
Task statuses: - pending: Task not yet started - in_progress: Task currently being worked on - completed: Task finished
Best practices: - At least one task should be in_progress at any time - Use activeForm to describe what’s happening (e.g., “Running tests”) - Update status as work progresses
- __init__(sandbox: SandboxAdapter)[source]¶
Initialize todo write tool.
- Parameters:
sandbox – Sandbox adapter instance
- execute(args: Dict[str, Any]) ToolResult[source]¶
Execute todo write tool to create or update TODO.md.
- Args:
- args: Tool arguments dictionary
- todos (list, required): List of todo items. Each item is a dictionary with:
content (str, required): Task content in imperative form. Example: “Run tests”, “Fix bug”, “Write documentation”
activeForm (str, required): Present continuous form describing the action. Example: “Running tests”, “Fixing bug”, “Writing documentation”
status (str, required): Task status. Must be one of: - “pending”: Task not yet started - “in_progress”: Task currently being worked on - “completed”: Task finished
- Returns:
ToolResult with: - ok (bool): True if TODO.md was written successfully (no errors in stderr) - stdout (str): Summary of updated TODO list with counts by status - stderr (str): Error messages if any (empty string means success) - meta (dict): Contains todo_file, todo_count, pending, in_progress, completed
- Examples:
# Create initial TODO list todo_write(todos=[
- {
“content”: “Set up project structure”, “activeForm”: “Setting up project structure”, “status”: “in_progress”
}, {
“content”: “Write unit tests”, “activeForm”: “Writing unit tests”, “status”: “pending”
}
])
# Update TODO list (replaces entire list) todo_write(todos=[
- {
“content”: “Set up project structure”, “activeForm”: “Setting up project structure”, “status”: “completed”
}, {
“content”: “Write unit tests”, “activeForm”: “Writing unit tests”, “status”: “in_progress”
}
])
Important Notes: - This tool replaces the entire TODO.md file with the new todos list - To update a single task, read current todos, modify, then write back - At least one task should be in_progress (warning shown if none) - TODO.md is created in the workspace root directory
File Format: The tool generates markdown format: ```markdown # TODO
## In Progress - [ ] Task 1 (Running task 1)
## Pending - [ ] Task 2 (Will run task 2)
Error Handling: - Success is determined by stderr content, not exit code - If stderr is empty, the operation succeeded - Check stderr for specific error messages if ok=False