fix(agent): bound researcher web tool loop (#4313)

This commit is contained in:
Steven Enamakel
2026-06-29 18:20:26 -07:00
committed by GitHub
parent 300d70aa42
commit 3cebc6db2d
3 changed files with 29 additions and 35 deletions
@@ -1077,17 +1077,18 @@ mod tests {
}
#[test]
fn researcher_has_curl_for_artifact_downloads() {
fn researcher_is_bounded_to_search_and_fetch() {
let def = find("researcher");
assert_eq!(
def.max_iterations, 10,
"researcher keeps enough turns to recover from bad search results without broadening its tool surface"
);
match &def.tools {
ToolScope::Named(tools) => {
assert!(
tools.iter().any(|t| t == "curl"),
"researcher needs curl for artifact downloads"
);
assert!(
tools.iter().any(|t| t == "http_request"),
"researcher still needs http_request"
assert_eq!(
tools,
&vec!["web_search_tool".to_string(), "web_fetch".to_string()],
"researcher must stay limited to search+fetch so simple lookups do not fan out into deep research loops"
);
}
ToolScope::Wildcard => panic!("researcher must have Named tool scope"),
@@ -3,7 +3,7 @@ display_name = "Researcher"
delegate_name = "research"
when_to_use = "Web & docs crawler — reads real documentation, compresses to dense markdown. Use for any task that requires looking up external knowledge."
temperature = 0.4
max_iterations = 8
max_iterations = 10
iteration_policy = "extended"
max_result_chars = 8000
sandbox_mode = "none"
@@ -20,31 +20,10 @@ hint = "agentic"
[tools]
named = [
"http_request",
"curl",
"web_search",
# Keep the default researcher narrow: search to locate sources, fetch to read
# selected pages. Deep Parallel, market, filesystem, and general HTTP/curl
# tools belong to more specific agents so simple research tasks don't expand
# into open-ended search loops.
"web_search_tool",
"file_read",
# Coding-harness read-only primitives from #1208. `web_fetch` is the
# simple URL-GET sibling of `http_request` (capped body, same
# allowed_domains gate); grep/glob/list let the researcher navigate
# cached docs in the workspace without falling through to shell.
"web_fetch",
"grep",
"glob",
"list",
# Parallel — full surface (search/extract are also delegated by web_search_tool;
# chat/research/enrich/dataset unlock grounded answers and deep multi-step research).
"parallel_search",
"parallel_extract",
"parallel_chat",
"parallel_research",
"parallel_enrich",
"parallel_dataset",
# Stock / FX / crypto / commodity market data via the financial-apis backend.
"stock_quote",
"stock_exchange_rate",
"stock_options",
"stock_crypto_series",
"stock_commodity",
]
@@ -6,7 +6,6 @@ You are the **Researcher** agent. You find accurate, up-to-date information.
- Web search for current information
- HTTP requests to fetch documentation
- Read local files for project context
- Memory recall for prior research
## Rules
@@ -16,3 +15,18 @@ You are the **Researcher** agent. You find accurate, up-to-date information.
- **Compress output** — Distill long documents into dense, factual markdown summaries.
- **Cite sources** — Include URLs or file paths for information you reference.
- **Stay focused** — Answer the specific question asked, not everything tangentially related.
## Research Loop Contract
- Use `web_search_tool` to find likely sources, then `web_fetch` to read only the pages needed to answer.
- For simple factual requests, one focused search plus one or two fetched sources is enough unless results are empty or contradictory.
- Do not keep broadening, re-searching, or chasing tangents once you have source-backed evidence for the requested answer.
- Prefer fetching authoritative or primary sources over reading many secondary summaries.
- If search or fetch fails, return what happened under `Failed tool calls`; do not silently keep trying unrelated queries.
## Output Contract
- Always return an output to the orchestrator, even when the answer is incomplete.
- If you could answer, put the answer first, then list the URLs you used.
- If you could not answer, say exactly what is missing and what you tried.
- Never finish with only tool calls or internal notes; the orchestrator needs a compact synthesis it can pass on or evaluate.