The AI's Tools¶
When a capable model works on your project, it does not just emit code. It calls tools: reading a file, searching the project, editing one function, running a syntax check, looking something up on the web. Each call appears as a short line in the chat while it works. This page lists every tool, what it does, and when it is available.
The full list¶
| Tool | What it does | Available |
|---|---|---|
list_files |
The project's file tree with line counts. Skips build output, archives and virtual environments. | Multi-turn loops |
search_code(pattern) |
Grep-style search across the project. | Multi-turn loops |
read_code(file, target) |
Read a whole file, a named function or class, or a line range (offset / limit, the same shape Claude Code uses). |
Multi-turn loops |
glob(pattern) |
Find files by name pattern, for example ui/**/*.py. |
Multi-turn loops |
edit_code(file, old_text, new_text) |
Replace an exact text span. The workhorse for small changes. | Always |
edit_function(file, function_name, replacement_body) |
Replace one function's body, located by parsing the file rather than matching text. Preserves indentation. | Always |
multi_edit(file, edits) |
Several exact replacements in one file in one call. | Always |
create_file(path, content) |
Add a new file to the project. | Always |
delete_file(path) |
Remove a file, so a refactor can retire what it replaced instead of leaving it to be imported by mistake. | Always |
syntax_check(file) |
Compile a file and report the first syntax error. Cheap, and the loop nudges the model to use it after edits. | Always |
run_code |
Run the project the way Test Run does and return the output and any traceback. | Multi-turn loops |
bash(command) |
Run a shell command in the project directory, under the whitelist / confirm / deny safety model described on the Agent Mode page. | Agent Mode |
web_search(query) |
Search the web. | Agent Mode |
web_fetch(url) |
Read a page as text. | Agent Mode |
load_skill(name) |
Pull the full text of a lazy skill listed in the skill index. | Whenever lazy skills exist |
question(prompt, options) |
Ask you a structured question mid-generation instead of guessing. Three per generation; not offered in Agent Mode or during auto-fix. | Default mode |
Two kinds of loop¶
Whittl runs tool calls in one of two loops, and the difference explains why some tools only appear sometimes.
Single-turn. The model gets the relevant code injected up front and only the action tools: edit, create, delete, syntax check. No exploration tools, because everything it needs is already in the message, and offering read_code would only invite a round of re-reading. This is the default for every backend except Claude when Agent Mode is off. It usually finishes in one or two API calls.
Multi-turn. The model gets the full tool set and works agentically: read, search, edit, check, run, repeat. Claude always uses this loop. Other backends use it when Agent Mode is on and the model is tier-S or tier-A, and the auto-fix path uses it for any model when the project is too large to inject whole (see below). Round caps come from the tier: 10 by default, 20 for tier-A and 50 for tier-S in Agent Mode.
Large projects: index-only context¶
Injecting a whole project into every round is fine at ten files and ruinous at sixty. Above a size that scales with the model's context window, Whittl switches to an index: the model receives the file list with line counts and reads only what it needs with read_code and search_code. You will see this in the log:
The same switch applies to auto-fix. On one field project this took a fix round from 364,000 input tokens to about 15,000, and made a model with a 200K window able to attempt the fix at all.
Reading the chat lines¶
Every call is humanised in chat. A few you will see often:
→ Reading canvas.py
→ Editing CanvasWidget.auto_detect_all_objects() in canvas.py
→ Checking syntax
→ Searching the web: "flet 0.28 page.window deprecated"
→ Editing align_panel.py (failed: old_text not found ...)
A failed edit is not an error in Whittl. It means the model's old_text did not match the file exactly, usually because the file changed since it last read it. The loop tells it so, with the closest matching lines, and it re-reads and retries.
What the tools cannot do¶
- Leave the project. Every path is validated against the project directory.
../and absolute paths are rejected. - Touch
data/. Runtime and user data underdata/is never written by the tool loop. - Run arbitrary shell commands silently. Anything outside the
bashwhitelist asks you first; the deny list is blocked outright.
What's next¶
- Agent Mode — round caps, tiers, the
bashsafety model - Web Research — the two web tools in detail
- Skills System — lazy skills and
load_skill