Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🕵️ Day 24 — Research Agent (Multi-Tool Agent)

Part of my 100-Day AI Engineering Bootcamp Day 24 — building one AI project a day to become job-ready.

🤔 The Problem I Set Out to Solve

Days 22-23 gave the AI one tool each, in isolation. Today's goal: combine the calculator and web search into a single agent that picks the right tool — or chains both, in sequence, when a question genuinely needs it. The test case I built around: "What's 15% of the current Bitcoin price?" — a question with no answer unless you search first, then calculate using exactly what you found.

This one took three real bugs to get right, each more interesting than the last.

🪲 Bug #1 — The Model Narrated Instead of Calling

First attempt, with both tools wired up correctly: I asked the Bitcoin question and got back:

"To find 15% of the current Bitcoin price, I'll first need to look up the current price... /search_web current Bitcoin price (I'll wait for the search results...)"

No tool call expander appeared. The model typed out what a tool call looks like, as plain text, instead of emitting a real structured tool_calls request. I added a stronger system prompt insisting it must use search — that made it worse, not better, producing the same narration pattern with more confidence.

I went looking for why, and found I wasn't alone: other developers have hit the exact same symptom with llama-3.3-70b-versatile on Groq — tool calling that's "unreliable/broken," with the model narrating its intended action as a string instead of a real call, and "two successive runs of the same prompt resulting in one succeeding and one failing." This wasn't a prompt-wording problem. It was a model-reliability problem.

The fix: switch models entirely, to openai/gpt-oss-120b — the same model Groq's own official tool-calling documentation uses in its examples. Groq even maintains a separate, specially fine-tuned "Tool-Use" model variant, built specifically because their general-purpose models aren't optimized for this. Once switched, real tool calls started appearing immediately.

🪲 Bug #2 — The Fix That Broke the Fallback

With the new model, the sequential chain worked beautifully: search for Bitcoin's real price, then calculate 15% of that exact number, correct math both times, multiple runs in a row.

Then, on a later run, a new crash:

groq.BadRequestError: Tool choice is none, but model called a tool
failed_generation: '{"name": "search_web", "arguments": {"cursor": 0, "id": 2}}'

This was a bug in my own fallback code, not the model. My tool_use_failed recovery path retried the question without passing the tools parameter at all — but my system prompt was now so insistent ("you MUST use search_web") that the model tried to fake a tool call anyway, with no real schema to follow, inventing nonsense arguments (cursor, id) that didn't match my actual tool's expected shape.

The fix: the fallback now explicitly passes tool_choice="none" alongside the real tools schema — so the model can see what the tool looks like, but is given a hard, explicit instruction it cannot violate: don't call anything right now.

⚙️ What It Actually Does (when everything cooperates)

  • 🧮 Calls the calculator for math
  • 🔎 Calls web search for current information
  • 🔗 Chains them sequentially when a question needs both — search for a number, then calculate using exactly that number
  • 📋 Shows a step-by-step log of every tool call made, so you can watch the agent's reasoning unfold
  • 🛡️ Falls back gracefully, twice over now, if tool calling fails at the model level

🛠️ Tech Stack

  • Python
  • Groq API (openai/gpt-oss-120b) — switched from LLaMA 3.3 70B specifically for tool-calling reliability
  • ddgs (DuckDuckGo search wrapper)
  • Streamlit

🚀 How to Run

git clone https://github.com/PrashikSawant/Research-Agent
cd Day24-ResearchAgent
python -m venv venv
.\venv\Scripts\activate
pip install -r requirements.txt
# Add GROQ_API_KEY to .env
streamlit run app.py

💡 What I Actually Learned

  • Not all models on the same provider handle tool calling equally well — llama-3.3-70b-versatile and openai/gpt-oss-120b are both "function-calling capable" on paper, but only one of them reliably emitted real structured calls in my testing
  • A stronger system prompt can fix one problem and quietly create another — my fix for "the model won't search" caused "the model tries to fake a search call even when tools are disabled," because I'd made the instruction too forceful without constraining the fallback path to match
  • tool_choice="none" is a real, explicit way to forbid tool use for one specific call — silently omitting the tools parameter isn't the same thing, and a model conditioned strongly enough will still try to call something even with no schema in front of it
  • Multi-step agentic behavior (search → reason → calculate → answer) is genuinely a different engineering problem than single-tool calling — more moving parts, more failure surface, and the bugs compound on each other instead of staying isolated

🔮 What's Next

Day 25 — Multi-Agent System with CrewAI, moving from one agent juggling multiple tools to multiple agents, each with their own role, collaborating on a shared task.

👤 About Me

I'm Prashik, building one AI project a day for 100 days to become a job-ready AI Engineer. Follow my journey on LinkedIn.

About

Day 24 of my AI Engineering Journey — Built a multi-tool agent chaining calculator + web search. Fixed a model faking tool calls as text, then a fallback bug where the same fix made it fake calls with tools disabled. Two opposite failures, one root cause.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages