Working with multiple AI agents, I kept hitting the same problem: each agent was making duplicate tool calls, burning through my OpenAI budget like crazy.
The specific problem:
Multiply this by hundreds of daily tasks across multiple agents = budget nightmare.
Instead of each agent having its own tools, I built a shared registry that all agents access:
# Before: Scattered, duplicated tools
class MarketingAgent:
def __init__(self):
self.websearch = WebSearchTool() # Each agent = new instance
class AnalysisAgent:
def __init__(self):
self.websearch = WebSearchTool() # Duplicate!
# After: Shared registry with caching
@tool_registry.register("websearch")
class WebSearchTool:
def __init__(self):
self.cache = {}
self.cache_ttl = 3600 # 1 hour
async def execute(self, query: str):
cache_key = hashlib.md5(query.encode()).hexdigest()
if cache_key in self.cache:
logger.info(f"Cache hit for: {query}")
return self.cache[cache_key]
# Only make API call if not cached
result = await actual_web_search(query)
self.cache[cache_key] = result
return result
Cost reduction: 60% fewer API calls overall
Speed improvement: Cached responses in 50ms vs 2-3s for fresh calls
Consistency: All agents see the same data for the same query
Real example from my logs:
class ToolRegistry:
def __init__(self):
self._tools = {}
def register(self, tool_name):
def decorator(tool_class):
self._tools[tool_name] = tool_class()
return tool_class
return decorator
def get_tool(self, tool_name):
return self._tools.get(tool_name)
# Global registry
tool_registry = ToolRegistry()
# Any agent can access any tool
search_tool = tool_registry.get_tool("websearch")
result = await search_tool.execute("market trends 2024")
1. Debugging becomes trivial
All tool calls go through one place. Easy to log, monitor, and debug.
2. Rate limiting is centralized
Instead of each agent hitting limits, the registry manages quotas intelligently.
3. Tool upgrades are instant
Update the WebSearchTool once, all agents automatically get the new version.
4. A/B testing tools
Want to test a new search provider? Easy to swap in the registry without touching agent code.
If you're building multi-agent systems, consider:
Semantic caching is tricky. "competitor analysis" and "competitive landscape" should probably share a cache, but simple string matching misses this.
My solution: hash normalized queries (lowercased, stemmed, stop-words removed) for better cache hit rates.
Are you building multi-agent systems? What patterns have you found for managing shared resources?
Have you hit similar cost optimization challenges with AI APIs? How did you solve them?
Anyone using more sophisticated caching strategies like vector similarity for semantic matching?
This pattern was one of many lessons learned building a production AI orchestration system. The full technical deep-dive covers 15 architectural principles that emerged from months of debugging and optimization.
This is a useful pattern. I would pair the registry/cache layer with a gateway-level ledger, because caching only answers "did we avoid this call?" It does not always answer "who paid for the calls that still happened?"
For multi-agent SaaS, the cost record I want for every task is:
That is the angle we are taking with Tokens Forge: lower-cost routing matters, but the bigger win is making every model/tool call explainable after the fact. A shared tool registry cuts duplicate calls; a route ledger keeps the remaining spend accountable.