DEV Community

Abhinav Krishna K S
Abhinav Krishna K S

Posted on

Why my LangChain agent kept double-checking its own math

I built a small LangChain agent with three tools: a calculator, web search, and a Python code runner. The agent worked on the first try, until it didn't know when to stop.

I asked it to multiply two large numbers. The calculator returned the correct answer, and then the agent re-checked it four more times with other tools until it hit the recursion limit. The answer was right every time. The loop was the bug.

The setup

  • LangChain create_agent (built on LangGraph) with gemini-3.5-flash-lite
  • calculator: exact math using Python's ast module, no eval
  • web_search: live results through the ddgs package
  • python_repl: code execution in a subprocess with a 10-second timeout
  • Every step logged as [TOOL CALL], [TOOL RESULT] and [FINAL ANSWER]

Three fixes that made it reliable

1. Rewrite the tool descriptions.
The agent chooses tools from their descriptions. Mine overlapped, so the model saw two tools that could do the same job. Saying "this result is final and exact" on the calculator and "do not use for simple arithmetic" on the code runner removed most of the confusion.

2. Put guardrails in code, not only in the prompt.
A prompt rule like "don't re-verify results" was ignored by the smaller model. What worked was a loop guard in the run function that stops:

  • repeated identical tool calls
  • more than 3 calls to one tool
  • 2 errors in a row from the same tool
  • more than 5 tool calls in total

When a guard fires, the agent is forced to give a final answer.

3. Make tool failures return text.
Each tool wrapper catches its own exceptions and returns a string starting with Error:. The agent then reads the failure like any other result and responds, instead of crashing the whole run.

One bug worth knowing about

When a guard forced a final answer, the model once invented a number that was off by a few digits, even though the tool had returned the right one. The fix was to pass the latest successful tool result directly into the forcing message and tell the model to use those exact digits. Always compare the final answer with the tool output, not just the tool output with the truth.

What the tests showed

  • A general-knowledge question was answered directly with no tool call
  • A large calculation used one calculator call
  • "Find India's population, then compute people per km²" used web search, then the calculator, with the number found by the search
  • A divide-by-zero and a forced network failure both ended in a clear message, not a crash

Takeaway

An agent is only as reliable as the guardrails around it. Clear tool descriptions, limits in code, and errors treated as data mattered more than the choice of model.

I wrote up the full build, the test logs and the lessons in my longer article.

Read the full article: https://valentiuskryptix.com/a-practical-guide-to-build-an-langchain-ai-agent-that-uses-its-own-tools/

Code and logged runs: https://github.com/KRISH18833/langchain-agent

Top comments (0)