It's tempting to solve every "logic" with a tool. You get a system that's "modular", "auditable", "testable". But each extra tool:
And many times, the "logic" you're encapsulating is something the LLM does for free and better.
Ask this question before creating any tool:
Does the operation need access to data, systems, or guarantees the model doesn't have?
| Needs | Tool yes | Tool no |
|---|---|---|
| Read/write your DB | ✓ | |
| Call an external API | ✓ | |
| Side effects (mails, payments, notifs) | ✓ | |
| Absolute determinism (financial calc) | ✓ | |
| Real-time data (prices, stocks) | ✓ | |
| Translate / normalize / rephrase | ✓ (system prompt) | |
| Summarize content in context | ✓ (in-prompt) | |
| Decide tone / response style | ✓ (system prompt) | |
| Simple calculation with visible numbers | ✓ (in-prompt) | |
| Classify text into known categories | ✓ (in-prompt or output schema) |
The ship had an MCP with 23 tools. Forge audited and found 8 of them were "normalizers": normalize_alias, format_date, parse_priority, expand_abbreviation. All of them could be replaced by two paragraphs in the system prompt stating the normalization rules.
Result of deleting the 8: the agent got 1.4x faster, the catalog dropped to 15 tools, and the precision on picking the remaining tools went up (less noise, better decision).
Before writing a tool, ask: does this need the real world, or does it only need the model to think a bit more in the prompt? If it's the second, it's not a tool.