mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-03-22 02:15:42 +08:00
3.2 KiB
3.2 KiB
s02: Tool Use
s01 > [ s02 ] s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12
"The loop didn't change" -- adding tools means adding handlers, not rewriting the loop.
Problem
With only bash, the agent shells out for everything. cat truncates unpredictably, sed fails on special characters, and every bash call is an unconstrained security surface. Dedicated tools like read_file and write_file let you enforce path sandboxing at the tool level.
The key insight: adding tools does not require changing the loop.
Solution
+--------+ +-------+ +------------------+
| User | ---> | LLM | ---> | Tool Dispatch |
| prompt | | | | { |
+--------+ +---+---+ | bash: run_bash |
^ | read: run_read |
| | write: run_wr |
+-----------+ edit: run_edit |
tool_result | } |
+------------------+
The dispatch map is a dict: {tool_name: handler_function}.
One lookup replaces any if/elif chain.
How It Works
- Each tool gets a handler function. Path sandboxing prevents workspace escape.
def safe_path(p: str) -> Path:
path = (WORKDIR / p).resolve()
if not path.is_relative_to(WORKDIR):
raise ValueError(f"Path escapes workspace: {p}")
return path
def run_read(path: str, limit: int = None) -> str:
text = safe_path(path).read_text()
lines = text.splitlines()
if limit and limit < len(lines):
lines = lines[:limit]
return "\n".join(lines)[:50000]
- The dispatch map links tool names to handlers.
TOOL_HANDLERS = {
"bash": lambda **kw: run_bash(kw["command"]),
"read_file": lambda **kw: run_read(kw["path"], kw.get("limit")),
"write_file": lambda **kw: run_write(kw["path"], kw["content"]),
"edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"],
kw["new_text"]),
}
- In the loop, look up the handler by name. The loop body itself is unchanged from s01.
for block in response.content:
if block.type == "tool_use":
handler = TOOL_HANDLERS.get(block.name)
output = handler(**block.input) if handler \
else f"Unknown tool: {block.name}"
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
Add a tool = add a handler + add a schema entry. The loop never changes.
What Changed From s01
| Component | Before (s01) | After (s02) |
|---|---|---|
| Tools | 1 (bash only) | 4 (bash, read, write, edit) |
| Dispatch | Hardcoded bash call | TOOL_HANDLERS dict |
| Path safety | None | safe_path() sandbox |
| Agent loop | Unchanged | Unchanged |
Try It
cd learn-claude-code
python agents/s02_tool_use.py
Read the file requirements.txtCreate a file called greet.py with a greet(name) functionEdit greet.py to add a docstring to the functionRead greet.py to verify the edit worked