web_research function tool: the orchestrator decomposes the user’s problem and plans,
and each tool call is delegated to Parallel as a full grounded-research answer. The
orchestrator sees finished, synthesized answers — not raw search results — so its job
reduces to planning sub-questions and reconciling what comes back.
The tool definition
The tool takes a single argument — a complete, self-contained question — and returns an answer:Writing the tool description
The tool description is the contract that shapes how the orchestrator uses the tool — it is the highest-leverage text in this pattern. Best practices:- Say it returns a synthesized answer, not search results. Orchestrators trained on
web_search-style tools will otherwise issue keyword queries and plan to read results themselves. Words like “answers a question” and “(not raw results)” flip it into asking full questions. - Demand the complete, self-contained question. The subagent has no conversation
context — every constraint (dates, units, qualifiers, ambiguity resolution) must travel
inside the one
querystring. Repeat this in both the tool description and the parameter description. - Bias toward one thorough call first. State that a single call already performs multi-hop research, so the orchestrator doesn’t pre-decompose a question the subagent could answer whole — decomposition should be reserved for genuinely independent parts or gaps left after the first answer. This is your main lever on cost and latency.
- Keep one required parameter. A single
querystring is hard to misuse. If you want the orchestrator to control research depth, add an optionaleffortenum (low|medium|high) with guidance like “use high only for questions that require extensive research” — and default it tolowin your handler.
Executing the tool
The handler is just a Responses API call:Python
Full orchestrator loop
One client for the orchestrator (here OpenAI), one for the Parallel tool backend:Python
Operational guidance
- Execute independent tool calls concurrently. When a question has independent parts,
the orchestrator should issue those
web_researchcalls in the same turn and your handler should run them concurrently (e.g.asyncio.gather) — wall-clock stays close to a single call instead of the sum. - Pick the tier per call:
lowfor cheap breadth across many sub-questions,highfor the hardest single lookups. - Cap the tool budget and force a final answer when it is exhausted (as above), so a runaway orchestrator can’t loop indefinitely.
- The same pattern works with any tool-calling orchestrator — see Anthropic Tool Calling and OpenAI Tool Calling for provider-specific wiring.
Next steps
- Statefulness — an alternative to orchestration when all you need is follow-up questions on a prior answer