architectureagentic-designgeminisystems-engineering

How we reduced LLM cognitive load with the Sub-Agent-as-a-Tool pattern

Piling 15+ complex tools into a single LLM was causing context confusion. Here's why we bypassed top-level routing, embraced the Sub-Agent-as-a-Tool pattern, and built a generic multi-agent backend that scales.

Allan Bogh·

When we first built RidgeText, we followed the industry-standard "monolithic agent" pattern. We had one core LLM loop powered by Google's Vertex AI, loaded with a system prompt that described everything our application could do, and a single array of 15+ tool declarations.

Whenever a user sent an SMS, that single brain decided whether to search Google, fetch local weather, lookup a wildfire perimeter, geocode coordinates, or generate a custom topo map.

It worked great in early testing. But as our feature set grew, our monolithic agent began to experience context congestion.

The LLM carried too much cognitive load. For simple weather queries, we were paying the high token price of heavier models (like Gemini 3.5 Flash and Pro) just so the model had the capacity to hold our entire system instructions list. Worse, the crowded tool list increased the risk of non-deterministic errors, such as the model entering infinite search loops when it got confused about when to look up coordinates vs when to fetch active radar.

This week, we completed a total refactor of our AI pipeline, moving away from a single massive agent to a modular, multi-agent hierarchy. By splitting the service into logical, focused sub-agents and a final presentation guardrail, we drastically reduced the cognitive load on our main model, making our tool execution incredibly reliable and 100% bulletproof.

Here is what we built, why we built it, and the design patterns behind it.


Why Top-Level Classifiers Fail

Our initial draft of this refactor centered around a fast, top-level "intent classifier." The idea was simple: when a user texts us, a small, cheap model inspects the text and routes it. If they ask about the weather, route them to a Weather Agent. If they ask about anything else, route them to the general agent.

It sounds perfect on paper, but it fails the moment it hits real-world user behavior.

Outdoor recreationists rarely ask single-purpose questions. Instead, they send compound, mixed-intent requests:

A top-level classifier cannot route these cleanly. If it sends the query to the Weather Agent, the user never gets their trail suggestion. If it sends it to the general agent, the general agent has to carry all the weather tools anyway, defeating the purpose of the refactor.


The Solution: Sub-Agents as Tools

To solve this, we embraced the Agent-as-a-Tool (or Sub-Agent-as-a-Tool) pattern. Instead of routing requests before they reach the main agent, we let the Main Orchestrator remain the central point of contact.

We started with our weather tools as a proof of concept. Rather than cluttering the core orchestrator with low-level geocoding, forecast fetching, alert parsing, and radar map rendering APIs, we stripped those weather-specific tools from the main registry. In their place, we registered a single, high-level sub-agent tool: get_weather_analysis.

In subsequent phases of our agentic refactor, we will be extending this exact same architecture to all related domains (including wildfire perimeters, trail condition maps, and calendar syncs). We also introduced a specialized formatting agent (the SMS Summary Agent) as the final step in the pipeline to guarantee beautiful, carrier-compatible output before dispatch.

Inbound SMSTwilio GatewayMain OrchestratorGemini 3.5 Flash / ProValidates & CoordinatesCompound Task PlannerWeather Sub-Agentgemini-3.1-flash-liteWeather ToolsNWS Forecasts & RadarSMS Summary Agentgemini-3.1-flash-lite (Formatter)Strips Emojis/MD | <900 CharsRemoves Raw Storage URLsOutbound SMSTo User's DeviceUser Messageget_weather_analysis()Returns ReportRaw TextFormatted Output

The Agent-as-a-Tool delegation flow. The Main Orchestrator handles compound user requests and coordinates tools, delegating weather-specific loops dynamically to the Weather Sub-Agent via a single tool call.

Now, when a user asks: "Suggest a 5-mile trail with a lake nearby and check the weather there," the Main Orchestrator handles it gracefully:

  1. It calls the local retrieve_trail_layer tool to find the lake trail.
  2. It calls the get_weather_analysis tool for the trail's coordinates.
  3. It calls generate_map to build the custom topographic map.
  4. It synthesizes the final message.

The main agent doesn't need to know how to geocode a city, fetch hourly forecasts, parse severe alerts, or draw radar reflections. It simply delegates the weather portion of the task to a specialized, dedicated subordinate and awaits the result.


Shattering the Monolithic Tool-Call Ceiling

Context congestion isn't just about prompt length; it also directly impacts safety limits.

To prevent AI systems from entering infinite loops, hallucinating recursive functions, or endlessly search-querying themselves when confused, we enforce a strict global tool-call limit (typically 10 steps per execution).

In a monolithic agent, every tool-call turn chips away at this single, global ceiling:

  1. User asks: "Find a campsite in Cle Elum and see if there are weather alerts there."
  2. Monolith calls get_coordinates for Cle Elum (Turn 1).
  3. Monolith calls find_nearby_campsites (Turn 2).
  4. Monolith calls retrieve_weather_alerts (Turn 3).
  5. Monolith calls generate_map (Turn 4).
  6. Monolith parses results and answers.

If the query is any more complex—such as checking multiple alternate campgrounds or layer selections—the monolith easily bangs against the 10-step ceiling and crashes or fails silently, providing a broken user experience.

Decentralized Budgets for an Intelligent Network

The Agent-as-a-Tool pattern solves this by decentralizing the tool-call budget. Because each sub-agent is an isolated, independent model instance, it operates under its own local, scoped tool limit.

When the Main Orchestrator calls the get_weather_analysis sub-agent tool, that single action represents just 1 step from the Orchestrator's perspective.

However, behind that single step, the Weather Sub-Agent spins up with its own fresh, independent budget of 10 tool calls. It can geocode cities, pull weather data, monitor severe warnings, and render composite radar map layers within its own micro-budget without ever touching the Orchestrator's master ceiling.

Comparison between monolithic global tool limits and decentralized per-agent limits

Comparison between a monolithic global tool-call ceiling and a decentralized, nested per-agent budget. Scoping tool limits per-agent prevents global loop recursion while scaling task capability.

This nested structure allows our system to execute up to a hundred theoretical tool-steps across an intelligent, cooperative network of agents with high resiliency, while keeping each individual loop perfectly protected from infinite recursion.


Sub-Agent Autonomy & Focus

When get_weather_analysis is invoked, we spin up an isolated, standalone instance of our Weather Sub-Agent (weatherAgent.js).

This sub-agent runs its own autonomous multi-turn loop on the ultra-cheap gemini-3.1-flash-lite model. It carries only 6 highly-focused tools: coordinate lookups, current weather feeds, active alerts, and four National Weather Service radar mapping tools.

By narrowing its scope, we unlocked major advantages:

The Weather Sub-Agent executes its tools, generates radar images, formats a comprehensive weather analysis, and returns it to the Main Orchestrator for final summarization.


The Universal Formatting Guardrail

Even with a highly-focused sub-agent, LLMs are fundamentally verbose and prone to using expressive formatting. While emojis and bold text (**bold**) look great in a web browser, they are highly disruptive over standard SMS and consume precious characters in multi-part messages.

To solve this deterministically, all compiled responses pass through a final Summary Agent before dispatch. It acts as an automated output guardrail:


A Generic Pattern for Infinite Scale

The beauty of the Sub-Agent-as-a-Tool pattern is that it is fully generic and infinitely extensible.

We have established a reusable framework for adding new domains. If we want to add expert wildfire analysis, trail maintenance reports, or complex trip planning, we don't need to bloat our core orchestrator's prompt or tools list. We simply register:

By dividing labor among a network of simple, cooperative sub-agents rather than trying to build a single "all-knowing" monolith, we've unlocked an architecture that scales sustainably in both intelligence and capability.

Text the weather agent

RidgeText uses a multi-agent backend to deliver lightning-fast, safety-focused mountain forecasts over standard SMS. No app or cellular data connection required.