The optimal deep research agent run time is not a constant you tune once and forget. It is a dynamic boundary set by query ambiguity, source convergence, and the marginal value of another search iteration—engineers who treat it as a fixed timeout either burn tokens on redundant crawls or cut off investigations that needed one more step.
The false comfort of a fixed timeout
A hardcoded 30-second or 2-minute limit is easy to ship. It appears in early prototypes because the scheduler needs a number, and any number defers the hard conversation about what “done” means.
But fixed windows ignore task shape. A query like “What is the melting point of tin?” needs one retrieval and a parse. A query like “Compare EU and US regulatory responses to AI foundation models in 2023–2024 with citations” needs decomposition, multiple source types, and cross-checking. Forcing both through the same deep research agent run time produces either wasted spend or truncated answers.
Worse, fixed timeouts interact badly with variable provider latency. If your search API or LLM backend stalls, the agent exhausts its window on retries, not research. The timeout measures wall time, not work done.
What actually determines deep research agent run time
Three forces dominate. Ignore any one and your agent misbehaves.
Query ambiguity and decomposition
A well-specified query decomposes into a known set of sub-questions. The agent can plan steps: fetch primary sources, fetch secondary analysis, reconcile. As ambiguity rises, the agent must first infer sub-questions, which consumes steps before any external grounding happens.
If the planner emits a new sub-question on step 5 that should have appeared on step 1, you have paid for rework. Measuring run time without measuring planning churn hides the real cost. For a concrete trace: a “list semiconductor subsidies by country” query might decompose cleanly into 5 country sub-queries. A “assess strategic risk in chip supply chains” query may spawn 3 rewrites as the agent realizes “strategic risk” needs geopolitical and fab-capacity lenses. The latter legitimately needs more steps, but only if each rewrite yields new sources.
Source saturation and marginal gain
The key signal is marginal information gain per step. Early steps pull high-value sources. Later steps hit duplicate blogs, cached summarizers, or tangential PDFs. Plot cumulative unique facts vs step count; the curve flattens.
A deep research agent run time should track that flattening, not the clock. When the last three steps added <2% new facts, stop. In practice “facts” can be extracted entities, distinct claims, or embedding-cluster additions. Exact string-set diff is naive; use a deduplication scorer that hashes normalized propositions.
Cost and latency budgets
Token spend is linear-ish with steps; user patience is not. A background report job can run 20 minutes. A chat sidebar answer cannot. Define a token budget and a wall-clock budget, and treat the smaller as a hard cap, not a target. If the token budget hits first, you traded latency for completeness—acceptable in batch. If wall-clock hits first in interactive mode, you owe the user a partial stream.
Designing explicit stop conditions
Replace the timeout with a loop that checks convergence and budgets. Minimal sketch:
class ResearchAgent:
def __init__(self, max_steps=10, gain_threshold=0.02, token_budget=200_000):
self.max_steps = max_steps
self.gain_threshold = gain_threshold
self.token_budget = token_budget
def run(self, query):
facts = set()
tokens_used = 0
for step in range(self.max_steps):
sources, step_tokens = self.search_and_read(query, step)
tokens_used += step_tokens
new_facts = self.extract_facts(sources)
marginal_gain = len(new_facts - facts) / (len(facts) + 1)
facts |= new_facts
if tokens_used >= self.token_budget:
break
if step > 2 and marginal_gain < self.gain_threshold:
break
return self.synthesize(facts), tokens_used
The gain_threshold is task-dependent. For legal research, set it near zero—missing one precedent is fatal. For market briefs, 3% is fine.
Configuration as data, not code:
{
"max_steps": 12,
"gain_threshold": 0.015,
"token_budget": 250000,
"primary_model": "anthropic/claude-3.5-sonnet",
"fallback_models": ["openai/gpt-4o", "meta/llama-3.1-70b"]
}
Using model routing and fallback to avoid runaway retries
Provider errors should not count against research steps. If your orchestration layer catches a 429 and backs off for 10 seconds, that time is dead. Spanning multiple providers fixes this only if the client routing is transparent.
When you span multiple providers, an OpenAI-compatible gateway like n4n.ai honors your routing directives and fails over on rate limits, so the deep research agent run time stays predictable instead of ballooning from retry storms. It also forwards cache-control hints, letting repeated prompt prefixes hit provider caches and shrink per-step latency.
A call with explicit routing looks like:
curl https://api.n4n.ai/v1/chat/completions \
-H "Authorization: Bearer $N4N_KEY" \
-H "X-Route-Model: anthropic/claude-3.5-sonnet" \
-d '{
"model": "anthropic/claude-3.5-sonnet",
"messages": [{"role":"user","content":"Synthesize the extracted facts"}],
"cache_control": {"type":"ephemeral"}
}'
The agent code stays unaware of which backend answered. That separation keeps stop logic about research, not transport.
Instrumentation: you can’t tune what you don’t log
Every run should emit step count, tokens per step, marginal gain per step, and final source count. A simple struct:
@dataclass
class RunTrace:
query: str
steps: int
tokens: int
gains: list[float]
stopped_reason: str # "gain", "budget", "max_steps"
Aggregate these per query cluster. If 80% of “compare” queries stop at gain threshold but average 9 steps, while “define” queries hit max_steps with near-zero gain, your threshold is wrong for the second class. Split configs by intent classifier.
A worked example: two queries, two run times
Query A: “What is the population of Uruguay?” The agent step 1 fetches census, extracts number, gain 100%. Step 2 finds a blog quoting the same number, gain 0%. Stop at step 2. Total deep research agent run time: 4 seconds, 1.2k tokens.
Query B: “Evaluate carbon capture viability for cement plants in Southeast Asia.” Step 1–3 pull academic papers and IEA reports. Step 4–6 add country-specific pilot projects. Step 7–9 surface financing mechanisms. Marginal gain stays above 4% until step 9, then drops to 1%. Stop at step 10 by threshold. Run time: 3 minutes, 180k tokens.
Same code, different outcome. The fixed-timeout alternative would either truncate B at 30s (useless) or waste 90s on A (expensive at scale).
Tradeoffs: when longer is worse
Running longer is not inherently better. Three failure modes:
Staleness. In fast-moving topics (earnings, outages), a 15-minute crawl collects superseded statements. The final synthesis may weigh outdated sources equally.
Overfitting to noise. Beyond saturation, new sources are often low-quality scrapes. The agent’s extractor may hallucinate structure from garbage, reducing answer precision.
User abandonment. For interactive surfaces, a deep research agent run time beyond ~30 seconds without streaming intermediate status loses the user. They rephrase or leave.
Conversely, cutting short on complex tasks produces confident under-research. The agent fills gaps with model priors, which is exactly what retrieval was meant to prevent.
Decisive takeaway
Set the deep research agent run time through explicit stop conditions: a marginal-gain threshold, a step cap, and a token budget. Measure gain per step empirically for your domain and tune the threshold there, not in a slack thread. Use a gateway that abstracts provider degradation so transport faults don’t masquerade as research progress. Ship the adaptive loop, log the step count and final gain, and review weekly—the right number is a curve, not a constant.