Skip to main content

Advanced: Web Research and Model Cost Tiering

Let flagship models plan and synthesize while cheaper models do the token-heavy reading with built-in web tools — and measure the split's real payoff: event-stream attribution, fair control experiments, and when not to use it.

This page covers cost tiering in the multiagent coordinator pattern: let the flagship model plan and synthesize while token-heavy reading goes to cheaper models, and measure the split's real payoff. The full multi-agent chain — configuration shape, orchestration tools, thread observation — is covered in Advanced: Multi-Agent Custom Proposals; this page focuses on cost: why the architecture lowers the bill, how to measure it, and when not to use it.

Scenario: reading is the main cost

Most agent workloads contain two very different kinds of work: a small amount of planning and judgment, and a large amount of mechanical reading and execution. Web research is the extreme case — verifying twenty facts means sending hundreds of thousands of tokens of web page content through the model. At flagship rates, that reading accounts for most of the bill, yet reading itself does not need flagship judgment. The coordinator pattern splits the two loads: a flagship coordinator plans the research, decomposes sub-questions, and synthesizes the answer, never reading raw pages directly; cheap workers do all the reading in their own parallel threads and return only distilled findings. The same reading tokens now bill at the cheap rate — that is the entire point of cost tiering. The same cost logic applies to any workload where a cheaper model can handle the token-heavy processing: document review, log analysis, codebase scans.

Architecture: reading stays in worker threads

Question
   │
   ▼
Flagship coordinator (qwen3.8-max, no business tools of its own)
   │  create_agent / list_agents / wait_for_agents (injected by the platform)
   ├──────────────┬──────────────┬─────────→ parallel sub-questions
   ▼              ▼              ▼
worker A       worker B       worker C … (qwen3.7-plus, each in its own session thread)
web_search → web_fetch ×N (built-in tools)
   │              │              │
   └── findings and source URLs returned in the final message ──┘
   ▼
coordinator synthesizes → final answer
The cost advantage rests on two structural properties:
  1. Reading content does not cross threads. The search results and pages a worker reads live only in its own thread context; the coordinator receives small messages (delegated sub-questions) and distilled findings. This is directly verifiable in the event stream: worker threads show dense tool_call / tool_call_output for web_search / web_fetch, while the coordinator's main thread shows only orchestration calls and the final synthesis — the raw bulk never appears in any main-thread event.
  2. Rates follow the model ID. An agent's model field only needs { id }; capability and price tier follow the ID itself. Use different IDs for coordinator and workers, and the bill naturally splits into two columns — model ID is also the most direct dimension for cost attribution.
Parallelism is a side benefit: workers run in independent threads, so wall-clock time is shorter too.

Configure a two-model team

Use currently available IDs: flagship coordinator qwen3.8-max, cheap worker qwen3.7-plus (the cheaper qwen3.6-flash tier is also available). Legacy general IDs like qwen3-max are rejected with 400; check the console for the current list.
export BASE="https://{workspace_id}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio"
export DASHSCOPE_API_KEY="<your DashScope API Key>"

Worker: cheap model + built-in web tools

Built-in tools remove a layer of provisioning and credentials compared with marketplace MCP — enable web_search and web_fetch explicitly in the same builtin_toolkit, and no mcp_servers is needed:
curl -X POST "$BASE/agents" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "search_worker",
    "model": { "id": "qwen3.7-plus" },
    "tools": [
      { "type": "builtin_toolkit",
        "default_config": { "enabled": false },
        "configs": [
          { "name": "web_search", "enabled": true },
          { "name": "web_fetch", "enabled": true }
        ] }
    ],
    "system": "You are a search worker researching one focused sub-question for a coordinator. Use web_search to locate sources and web_fetch to read promising pages. Prefer primary sources, try alternative queries when evidence is weak, and cross-check important claims. Your final message must contain concise findings, source URLs, and supporting facts; a submission receipt alone is not a delivery. Do not return full page text. If no definite answer emerges, state what remains uncertain."
  }'
The tool names must keep their underscores (web_search / web_fetch, not websearch / webfetch). Each worker instance researches one focused sub-question in its own session thread — the huge pages it reads never enter anyone else's context.
Choosing a web tool. web_search / web_fetch cover search and static reads; when you need to click pages or fill forms, use browser_use from an enabled MCP service instead (service and tool names come from the console service catalog). The two paths use different tool names — the names your system prompt references must match what is actually enabled.

Coordinator: flagship model, no business tools, just a roster

The coordinator gets no tools — it has no direct channel to anything outside its roster. What makes it a coordinator is the multiagent field: the service injects create_agent / list_agents / wait_for_agents (workers get submit_result), so none of these need to be defined:
curl -X POST "$BASE/agents" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "search_coordinator",
    "model": { "id": "qwen3.8-max" },
    "multiagent": {
      "type": "coordinator",
      "agents": [
        { "type": "agent", "id": "<the search_worker agent id>" }
      ]
    },
    "system": "You are coordinating a team of search workers to answer a hard web-research question. Your workers have web tools; you do not. Break the question into focused sub-questions, delegate them to workers via create_agent, and run several in parallel on independent sub-questions (four by default, at most). After spawning, always call wait_for_agents before drawing any conclusion. When a worker reports, judge whether it answered the sub-question; if evidence is thin, delegate once more with different phrasing. Once evidence suffices, synthesize the workers' findings into a single final answer to the original question, keeping source URLs."
  }'
From there, follow the standard chain in the multi-agent page: create an Environment, create a Session mounted on the coordinator, and POST one message event.
Roster version semantics (see the multi-agent page): a member without version resolves to the worker's latest version at every delegation — change the worker without touching the coordinator; write version explicitly to freeze a reproducible team.
The coordinator only knows what you write in its prompt. The service does not expose worker system prompts or tool details to the coordinator; its understanding of worker behavior comes entirely from the description in its own prompt. Misaligned descriptions degrade delegation quality — aligning them is the responsibility of the configuration author, and the service does not enforce it.

Verify the single-worker chain first

With only one research question, use a worker directly. Recommended order: web_search to find candidate sources → web_fetch to read the relevant pages → check conclusions against sources and answer with URLs. When a conclusion depends on page details, skimming search snippets is no substitute for reading the page. This step doubles as a smoke test before adding the coordinator: confirm both tools show successful calls in the worker thread and the final message carries sources.

Measuring the split

Two data paths let you evaluate the architecture's cost profile: Path 1: group the event stream (after the fact, no extra infrastructure). Every model call produces a model_request_end event whose payload carries model, input_tokens / output_tokens / cache_read_input_tokens / cache_creation_input_tokens, and whose top level carries thread_id. Bucket by thread_id to split "coordinator thread vs worker threads"; bucket by data.model to split "flagship column vs cheap column" — both bills read straight out of the event stream. Path 2: time window × model ID. In workspace-level usage data, cut by run window and model ID: the team run shows two rows (flagship + cheap), the single-flagship control shows one. Procedure: run the team, note the window; run the control, note its window; extract usage separately. Statistics and pricing follow the billing documentation.
Web tool calls bill separately from model inference (web_search bills per call; web_fetch is currently free for a limited time). Swapping an old MCP setup for built-in tools changes that tool-cost component, so both configurations need fresh measurement.

Designing a fair control experiment

To answer "what would this cost without the pattern", the realistic alternative is one flagship agent with the same built-in web tools (identical tool configuration; only the model ID changes to flagship). One key point decides whether the comparison is meaningful: strictness must match. Left unconstrained, a lone flagship will cut costs — reading a single source per fact and considering the job done — but that is a lower-strictness product, not the same job at a different price. The control prompt must state what the team already does: at least two independent verifications per fact, re-fetch and flag when sources conflict, and two source URLs per fact in the answer.

Counterfactual estimate

To see "what if all reading billed at flagship rates", multiply the team run's token counts by flagship rates and compare with the actual tiered split (reading at the cheap rate). Cache write/read multipliers follow the billing documentation — cache_read_input_tokens / cache_creation_input_tokens in model_request_end are the raw fields for such estimates. The hypothesis to validate: transfer most reading tokens to the cheap workers while preserving answer quality. Matching strictness makes the comparison meaningful, but it does not guarantee equal token volumes or a lower team total; measure actual tokens, delegation overhead, and tool fees separately.
A successful tool call is not a delivered conclusion. In testing, a worker may first emit a message containing only a submission receipt, and the coordinator needs send_to_agent to request the full report. Require facts and source URLs in the worker's final message, and check what was actually delivered.

Cost guardrails

Sessions have no budget / spend cap field, so guardrails live at three levels:
  • Throttle at the scheduled-task layer: constrain trigger frequency (the cron schedule itself throttles), so the same job is not launched repeatedly. Note that concurrent triggers do not error (two back-to-back /run calls each create a run and finish in parallel) — cap concurrency at the trigger side, see Production;
  • Constrain fan-out in the prompt: write the worker cap, per-brief granularity, and stop conditions into the coordinator's system prompt — how many workers get spawned is entirely the coordinator's call, and the prompt is the only control point;
  • Reconcile after the run: compare per-model usage against the expected range, and tighten prompt granularity when it balloons.

Four cautions

  1. Compare at matched strictness. An unconstrained lone flagship reads less and costs less — but it is a different product. Only compare when the verification standard is fixed.
  2. Delegation has a fixed overhead. Every worker thread pays fixed setup cost. Splitting the same work into more, narrower briefs raises the bill; brief granularity has an optimum.
  3. Verification covers only what you put in. Both arms verified twenty facts, but the park list itself may come from model memory — the facts were audited, the decomposition was not. When premises matter, spend one more delegation to verify the premise first.
  4. The coordinator only knows what is written in its prompt. The accuracy of worker descriptions directly determines delegation quality — and whether the economics materialize.

When not to use the split

  • Narrow questions: too little reading for the rate gap to cover the overhead;
  • The coordinator answers from its own knowledge (no delegation happens): an extra flagship round-trip is incurred with no delegated output. The event stream shows a clear signal — a run with no thread_created at all, identifiable directly with the bucketed rendering in the multi-agent page;
  • The raw material itself needs flagship judgment (nuanced document analysis rather than fact-finding): a cheap reader may drop exactly the important part while distilling.

Summary

  • Cost tiering lands through model IDs: the flagship coordinator plans and synthesizes, never touching raw pages; cheap workers do all the reading in parallel threads;
  • Reading content does not cross threads — a structural property verifiable in the event stream (dense web_search / web_fetch on worker threads, only orchestration and synthesis on the main thread);
  • Two measurement paths: model_request_end grouped by thread_id / model (event layer); time window × model ID (usage layer). Control experiments must match strictness, or you are comparing two different products;
  • Three guardrail levels: scheduled-task throttling, prompt-constrained fan-out, post-run reconciliation.
Cleanup matches the multi-agent page: archive Session / Environment / Agent one by one (archiving keeps the audit record and stops metering).

Next steps