diff --git a/src/openhuman/agent_registry/agents/loader.rs b/src/openhuman/agent_registry/agents/loader.rs index f1c8a256d..77e22396d 100644 --- a/src/openhuman/agent_registry/agents/loader.rs +++ b/src/openhuman/agent_registry/agents/loader.rs @@ -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"), diff --git a/src/openhuman/agent_registry/agents/researcher/agent.toml b/src/openhuman/agent_registry/agents/researcher/agent.toml index 9c8f4c958..476fb8469 100644 --- a/src/openhuman/agent_registry/agents/researcher/agent.toml +++ b/src/openhuman/agent_registry/agents/researcher/agent.toml @@ -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", ] diff --git a/src/openhuman/agent_registry/agents/researcher/prompt.md b/src/openhuman/agent_registry/agents/researcher/prompt.md index 117f033d8..c8600290a 100644 --- a/src/openhuman/agent_registry/agents/researcher/prompt.md +++ b/src/openhuman/agent_registry/agents/researcher/prompt.md @@ -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.