{"slug": "what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools", "title": "What If Your AI Agent Doesn't Need Better Prompts — Just Better Tools?", "summary": "A developer argues that AI agents often fail not due to poor prompts but due to a lack of real tools, and demonstrates how equipping an agent with simple functions like running tests can dramatically improve performance. The post includes a code example and practical advice for building tool-using agents.", "body_md": "I rewrote the system prompt fourteen times.\n\nVersion 3 was \"be thorough.\" Version 7 was a 900-word manifesto about edge cases. Version 12 threatened the model if it hallucinated a file path. Version 14 still booked a meeting on the wrong calendar and cheerfully summarized the disaster.\n\nThe agent wasn't dumb. It was *unarmed*.\n\nIf you've been stuck in prompt-tweaking hell with an AI agent that keeps almost-working, this is the post I wish I'd read first. The fix usually isn't another paragraph of instructions. It's giving the thing a real tool.\n\nA prompt is a pep talk before a job interview. A tool is the résumé, the laptop, and the door badge.\n\nYou can coach someone forever on \"be professional and double-check details.\" If they can't open the calendar API, they will invent a meeting time that sounds right. LLMs are the same — world-class at *sounding* competent, terrible at *touching* the real world unless you wire them up.\n\nThat's the agentic AI shift in one sentence: stop asking the model to *pretend* it did something. Give it a function it can actually call.\n\nMy agent had one job: when a GitHub issue is labeled `needs-repro`\n\n, clone the repo, run the failing test, and paste the output back.\n\nI tried better prompts first — \"always clone before you speculate,\" \"never invent stack traces,\" \"if you're unsure, say so.\" It invented a beautifully formatted stack trace from a file that didn't exist. From the model's point of view, a plausible stack trace *is* the assignment when the only tool it has is \"generate text.\"\n\nThen I registered three boring tools: `clone_repo(url)`\n\n, `run_tests(path)`\n\n, `comment_on_issue(number, body)`\n\n. No poetry. Next run: clone → run → paste real output. The intelligence didn't jump. The *surface area of reality* did.\n\n``` python\nimport json, subprocess\nfrom dataclasses import dataclass\nfrom typing import Callable\n\n@dataclass\nclass Tool:\n    name: str\n    description: str\n    schema: dict\n    handler: Callable[[dict], str]\n\ndef run_tests(args: dict) -> str:\n    path = args[\"path\"]\n    # Never let the model shell out raw — pin the command.\n    result = subprocess.run(\n        [\"pytest\", path, \"-q\"],\n        capture_output=True, text=True, timeout=120\n    )\n    return (result.stdout or result.stderr)[-4000:]\n\nTOOLS = {\n    \"run_tests\": Tool(\n        name=\"run_tests\",\n        description=\"Run pytest on a path; return the tail of output.\",\n        schema={\n            \"type\": \"object\",\n            \"properties\": {\"path\": {\"type\": \"string\"}},\n            \"required\": [\"path\"],\n        },\n        handler=run_tests,\n    ),\n}\n\ndef tools_for_llm() -> list[dict]:\n    \"\"\"Send names/descriptions/schemas — not handlers.\"\"\"\n    return [{\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": t.name,\n            \"description\": t.description,\n            \"parameters\": t.schema,\n        },\n    } for t in TOOLS.values()]\n\ndef dispatch(tool_name: str, arguments_json: str) -> str:\n    tool = TOOLS[tool_name]\n    return tool.handler(json.loads(arguments_json))\n\n# Loop: messages + tools_for_llm()\n# tool_call -> dispatch() -> append result -> repeat\n# stop on normal message or max-steps guard\n```\n\nNotice what the prompt no longer has to say: \"please don't invent pytest output.\" The model can't invent what `run_tests`\n\nalready returned. Reality is a function return value, not a writing style.\n\n**1. If the model must touch the world, it needs a tool.**\n\nEmail, APIs, files, tests, databases — tools, not adjectives in a system prompt.\n\n**2. Prefer boring, narrow tools over one god-tool.**\n\n`run_tests(path)`\n\nbeats `do_whatever(shell_command)`\n\n. Narrow tools are easier to log and sandbox. God-tools are how you wake up to a deleted directory and a polite apology.\n\n**3. Put constraints in code, not in prose.**\n\nTimeouts, allow-lists, max bytes, path sandboxes belong in the handler. The model is a creative writer under deadline. Your handler is the adult in the room.\n\n**4. Log tool calls like production traffic.**\n\nName, args, duration, success/fail. When an agent goes weird, you won't debug prompt vibes — you'll debug the trace: *it called clone_repo with a typo URL three times.*\n\nImagine a pizza shop where the only employee is a poet. Hand them a long script about greeting customers and using the oven. Without an oven dial, a ticket printer, and a delivery map, you don't have a pizza shop — you have spoken-word night with cheese anxiety.\n\nAgents are the same. Prompting is coaching the poet. Tool-use is installing the oven. Multi-agent setups multiply the moral: researchers need search, coders need file/test tools, reviewers need diffs. More agents with no tools is just a group chat with confidence issues.\n\nPrompts are great at role (\"prefer failing closed\"), output shape (\"short summary after tools\"), and tie-breaking (\"prefer the read-only tool\"). They're bad at physics. \"Don't hallucinate test output\" is physics. Solve physics with a tool.\n\nPick one task your current bot fakes:\n\n`fetch_invoice`\n\n, `list_open_prs`\n\n, `tail_logs`\n\n).If success jumps, you didn't find a better spell. You handed the wizard a screwdriver.\n\nAgentic AI feels magical in demos because demos hide the plumbing. In production, the magic is mostly **tool surface area + boring guardrails + a short honest prompt**.\n\nStop asking your agent to role-play competence. Give it hands. Keep the prompt short enough that you can still read it without scrolling past your own despair.\n\n**Your turn:** What's one tool you wish your agent had yesterday — the specific function, not a vibe? Drop the name and two args in the comments. I'm collecting a hall-of-fame of \"why didn't I add this sooner\" tools.", "url": "https://wpnews.pro/news/what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools", "canonical_source": "https://dev.to/aninmukhe/what-if-your-ai-agent-doesnt-need-better-prompts-just-better-tools-5ba7", "published_at": "2026-08-31 11:10:56+00:00", "updated_at": "2026-08-31 11:22:15.138067+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "developer-tools", "machine-learning", "large-language-models"], "entities": ["GitHub"], "alternates": {"html": "https://wpnews.pro/news/what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools", "markdown": "https://wpnews.pro/news/what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools.md", "text": "https://wpnews.pro/news/what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools.txt", "jsonld": "https://wpnews.pro/news/what-if-your-ai-agent-doesn-t-need-better-prompts-just-better-tools.jsonld"}}