Three Tools That Enable an Agent to Research, Code, Debug, and Save in One Conversation

The article demonstrates how combining three simple tools—fetch_url, write_file, and run_python—allows an AI agent to autonomously research web content, generate Python code, execute and debug it, and finally store the results, all within a single conversational loop.

DeepHub IMBA
DeepHub IMBA
DeepHub IMBA
Three Tools That Enable an Agent to Research, Code, Debug, and Save in One Conversation

An agent fetched a Python documentation page, wrote three list‑comprehension examples, and ran them. The first two succeeded; the third raised a syntax error. Instead of stopping, the agent read the error message, identified the problem, corrected the code, and reran it successfully, illustrating true "agentic" behavior.

The core of this capability is a trio of tools: fetch_url: retrieves any webpage, strips HTML tags with a simple regex, and returns up to 2500 characters of readable text. write_file: saves supplied text to a file inside a designated output directory. run_python: writes Python code to a temporary file and executes it via subprocess.run, returning stdout and stderr while enforcing a 15‑second timeout.

Below is the complete implementation of a multi‑tool agent that can research, write, execute, and persist results:

import anthropic
import subprocess, sys, tempfile, re
import urllib.request
from pathlib import Path
client = anthropic.Anthropic()
OUTPUT_DIR = Path("agent_output")
OUTPUT_DIR.mkdir(exist_ok=True)

def fetch_url(url: str) -> str:
    """Fetch a webpage and strip HTML - gives the agent access to the web."""
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
        with urllib.request.urlopen(req, timeout=10) as r:
            html = r.read().decode("utf-8", errors="ignore")
        text = re.sub(r"<[^>]+>", " ", html)
        text = re.sub(r"\s+", " ", text).strip()
        return text[:2500]
    except Exception as e:
        return f"Error fetching {url}: {e}"

def write_file(filename: str, content: str) -> str:
    """Save content to the output directory."""
    path = OUTPUT_DIR / filename
    path.write_text(content)
    return f"Saved {len(content)} chars to {path}"

def run_python(code: str) -> str:
    """Execute Python code in a subprocess. Returns stdout and stderr."""
    with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
        f.write(code)
        tmp = f.name
    try:
        result = subprocess.run([sys.executable, tmp], capture_output=True, text=True, timeout=15)
        out = result.stdout or ""
        err = result.stderr or ""
        return (out + ("
ERROR:
" + err if err else "")).strip() or "Ran with no output."
    except subprocess.TimeoutExpired:
        return "Error: timed out after 15 seconds."
    finally:
        Path(tmp).unlink(missing_ok=True)

TOOLS = [
    {"name": "fetch_url", "description": "Fetch the text content of any webpage. Use for research.", "input_schema": {"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},
    {"name": "write_file", "description": "Save text to a file in the output directory.", "input_schema": {"type":"object","properties":{"filename":{"type":"string"},"content":{"type":"string"}},"required":["filename","content"]}},
    {"name": "run_python", "description": "Execute Python code and return the output. Use to test code you write.", "input_schema": {"type":"object","properties":{"code":{"type":"string"}},"required":["code"]}}
]

def execute_tool(name, inputs):
    if name == "fetch_url": return fetch_url(inputs["url"])
    if name == "write_file": return write_file(inputs["filename"], inputs["content"])
    if name == "run_python": return run_python(inputs["code"])
    return f"Unknown tool: {name}"

def run_agent(task: str):
    print(f"
Task: {task}
" + "="*50)
    messages = [{"role": "user", "content": task}]
    system = """You are a research and coding agent. When given a task:
1. Research first if needed (fetch_url)
2. Write any code required
3. Run the code to verify it works - fix it if it errors
4. Save the final result to a file
Be methodical. Show your reasoning before each tool call."""
    for i in range(15):
        response = client.messages.create(model="claude-haiku-4-5-20251001", max_tokens=1024, system=system, tools=TOOLS, messages=messages)
        if response.stop_reason == "end_turn":
            answer = next((b.text for b in response.content if hasattr(b, "text")), "Done.")
            print(f"
Done: {answer}")
            return answer
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                print(f"
  [{block.name}]")
                result = execute_tool(block.name, block.input)
                print(f"  → {result[:200]}{'...' if len(result)>200 else ''}")
                tool_results.append({"type": "tool_result", "tool_use_id": block.id, "content": result})
        messages.append({"role":"assistant","content":response.content})
        messages.append({"role":"user","content":tool_results})

run_agent(
    "Write three Python list comprehension examples - basic, filtered, and nested. "
    "Run each one to verify it works. Save a cheat sheet to 'list_comprehensions.md'."
)

The fetch_url implementation uses a regular expression to strip HTML tags—a coarse but sufficient approach for obtaining readable text, and the timeout prevents the agent from hanging on slow sites. The run_python function runs code in an isolated temporary file via subprocess, which is safer than using exec() and also guarded by a timeout to avoid infinite loops.

The system prompt defines a clear workflow—research, code, test, save—and the agent follows this rhythm naturally, without the steps being hard‑coded.

When a complex task is given, the observed execution sequence is: fetch URL → synthesize information → write code → run → read error → fix bug → rerun → save result. This workflow emerges from the model’s own reasoning rather than being explicitly orchestrated by the developer.

Consequently, the design of tools proves more critical than the choice of underlying LLM; a well‑crafted tool can elevate an agent’s capabilities dramatically.

One of the most notable behaviors is the agent’s ability to debug its own code: it reads the error output, understands the cause, and iteratively repairs the script—behavior that arises from the loop and tool usage rather than a pre‑written script.

An improvement suggestion is to add a read_file tool that reads existing files from the output directory. By giving the agent a task such as “read the previously generated list‑comprehensions cheat sheet, add two advanced examples, and update the file,” the same planning logic can be applied to a different workflow: read → analyze → extend → save.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonTool integrationAI Agentagentic workflowfetch_urlrun_python
DeepHub IMBA
Written by

DeepHub IMBA

A must‑follow public account sharing practical AI insights. Follow now. internet + machine learning + big data + architecture = IMBA

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.