Build a supervisor multi-agent system
What you'll build: a content-request router that reads an incoming question, decides which of three specialist subagents should handle it — finance research, general research, or writing — and hands the request to that subagent's own prompt and tools, with the whole two-step run landing in one trace.
A supervisor (sometimes called a router or orchestrator) is a small model call whose only job is to classify: given a request, which of several specialists should take it? The pattern shows up anywhere one entry point needs to fan out to different tools, prompts, or personas depending on what's actually being asked — a support desk with a billing team and a technical team, a content pipeline with a data team and a copy team. This page builds the simplest real version of it: one classification call, one hand-off call.
This page ports langchain-samples/assistants-demo's
agents/supervisor/subagents.py. The original uses langgraph_supervisor.create_supervisor(...),
a LangGraph state machine with unbounded loops and a ROUTE_TO/COMPLETE text protocol.
This page replaces all of that with one response_format call and one runToolLoop() — no
langgraph dependency, no string parsing, no cycles.
The source's LangGraph version can chain subagents — e.g. research Tesla's earnings, then write a LinkedIn post from that research. This page builds the one-hop case only. To add multi-hop, extend Step 5's loop: feed one subagent's output into a second router call. That's the hybrid-port case, not covered here.
supervisor_flow.ipynb
is this whole page as one runnable notebook, written for a first-timer: a preflight cell that
checks whether your models are on the right kind of connection, the four tools and four prompts
built step by step, a live read of the one trace both calls land in, and four real ways to get
routing wrong. It renders on GitHub with its saved output, so you can read it through before
running anything.
1. Run the four tools standalone
The source assigns three subagents four tools total, defined once in
agents/react_agent/tools.py and shared across all of them:
| Subagent | Tools |
|---|---|
finance_research_agent | finance_research, basic_research, get_todays_date |
general_research_agent | advanced_research, get_todays_date |
writing_agent | basic_research, get_todays_date |
finance_research reads Yahoo Finance's own news endpoint; advanced_research and
basic_research are two depths of the same Tavily search, the same two configurations
Build a configurable ReAct agent uses.
Run all four standalone first, before any of this touches AcruxCore:
import asyncio
import requests
from tavily import AsyncTavilyClient
from datetime import datetime
# Yahoo's news-stream endpoint needs two calls in this order: a GET for a session
# cookie, then the POST. Both need a browser-shaped User-Agent.
YAHOO_NEWS_URL = "https://finance.yahoo.com/xhr/ncp?queryRef=latestNews&serviceKey=ncp_fin"
def _yahoo_headlines(ticker_symbol: str, limit: int = 3) -> str:
session = requests.Session()
session.headers.update({"User-Agent": "Mozilla/5.0"})
session.get("https://fc.yahoo.com", timeout=15)
res = session.post(YAHOO_NEWS_URL, timeout=20,
json={"serviceConfig": {"snippetCount": limit, "s": [ticker_symbol]}})
res.raise_for_status()
stream = res.json()["data"]["tickerStream"]["stream"]
return "\n\n".join(
f"{i['content']['title']}\n{i['content'].get('summary') or ''}".strip()
for i in stream[:limit]
)
async def _tavily_search(query, *, max_results, search_depth, include_images=False) -> list:
res = await AsyncTavilyClient().search(query, max_results=max_results,
search_depth=search_depth,
include_images=include_images)
return [{"title": r["title"], "url": r["url"]} for r in res["results"]]
async def finance_research(ticker_symbol: str):
return _yahoo_headlines(ticker_symbol)
async def advanced_research(query: str):
return await _tavily_search(query, max_results=10, search_depth="advanced")
async def basic_research(query: str):
return await _tavily_search(f"trending {query}", max_results=5,
search_depth="basic", include_images=True)
async def get_todays_date() -> str:
return datetime.now().strftime("%Y-%m-%d")
async def main():
print("=== finance_research(TSLA) ===")
print(await finance_research("TSLA"))
print()
print('=== advanced_research("LangGraph supervisor multi-agent pattern") ===')
results = await advanced_research("LangGraph supervisor multi-agent pattern")
print(f"{len(results)} result(s)")
for r in results[:3]:
print(f" - {r['title']} | {r['url']}")
print()
print('=== basic_research("AI content marketing") ===')
results = await basic_research("AI content marketing")
print(f"{len(results)} result(s)")
for r in results[:3]:
print(f" - {r['title']} | {r['url']}")
print()
print("=== get_todays_date() ===")
print(await get_todays_date())
asyncio.run(main())
Call each one to verify the underlying services respond before wiring anything to the gateway:
=== finance_research(TSLA) ===
Tesla (TSLA) Explores China Split As SpaceX Merger Talk Draws Attention
Reports indicate Tesla (NasdaqGS:TSLA) has explored separating its China operations to address
regulatory and supply chain issues. The proposed structure could support a future merger with
SpaceX, although Elon Musk has firmly denied that such a merger is planned.
=== advanced_research("LangGraph supervisor multi-agent pattern") ===
10 result(s)
- LangGraph Multi-Agent Supervisor | https://reference.langchain.com/python/langgraph-supervisor
- supervisor-pattern · GitHub Topics · GitHub | https://github.com/topics/supervisor-pattern
- Building Multi-Agent Systems with LangGraph-Supervisor | https://dev.to/sreeni5018/building-multi-agent-systems-with-langgraph-supervisor-138i
=== basic_research("AI content marketing") ===
5 result(s)
- How to adopt AI for content marketing: 2026 guide | Airtable | https://www.airtable.com/articles/ai-content-marketing
- AI-Driven Content Strategy: The Future of Marketing Innovation - Aprimo | https://www.aprimo.com/blog/ai-driven-content-strategy-the-future-of-marketing-innovation
- AI Will Shape the Future of Marketing | https://professional.dce.harvard.edu/blog/ai-will-shape-the-future-of-marketing
=== get_todays_date() ===
2026-08-02
2. Get an API key
The scripts below need one AcruxCore key to sync the tools, create the prompts, render
each one, and run the loop. Open Account & keys → New key, name it something like
supervisor-multi-agent, and copy the value — it's shown once.

export ACRUXCORE_API_KEY=acx_sk_...
export ACRUXCORE_BASE_URL=https://api.acruxcore.com/api/v1
export TAVILY_API_KEY=tvly-...
3. Create the four tools via the SDK decorator + tools.sync()
This is the first tutorial in this series to create tools the code-owned way: a Python function
decorated with @acrux.tool is the tool — its docstring becomes the model-facing
description, its signature becomes the JSON Schema, and tools.sync() reconciles that with the
catalog. Per this design's docstring-in-code decision, every docstring below is the source
repo's own text, kept verbatim — including its own typo ("finincial") and its own terse
Args: None on get_todays_date — because this page's framing is "the tool owns its
interface," and paraphrasing would contradict that:
"""
Create the four supervisor tools in the AcruxCore catalog via @acrux.tool + tools.sync().
Run once before supervisor_flow.py. Requires:
pip install acruxcore tavily-python requests
"""
import asyncio
from datetime import datetime
from typing import Optional, cast, Any
import requests
from acruxcore import AcruxCore, acrux
from tavily import AsyncTavilyClient
# _yahoo_headlines() and _tavily_search() are the two helpers from Step 1.
@acrux.tool
async def finance_research(ticker_symbol: str) -> Optional[list]:
"""Search for finance research, must be a ticker symbol. This tool is used to search for financial data and news from Yahoo Finance.
It will return related finincial news from Yahoo Finance for that given ticker symbol.
Args:
ticker_symbol (str): The ticker symbol of the company to research.
"""
return cast(Any, _yahoo_headlines(ticker_symbol))
@acrux.tool
async def advanced_research(query: str) -> Optional[list]:
"""Perform in-depth research with more results and deeper analysis. This tool
will return 10 results and go deeper for more information.
Args:
query (str): The query to search for.
"""
return cast(Any, await _tavily_search(query, max_results=10, search_depth="advanced"))
@acrux.tool
async def basic_research(query: str) -> Optional[list]:
"""This tool performs quick searches with little depth,
returning concise results ideal for basic research or quick queries.
Args:
query (str): The query to search for.
"""
return cast(Any, await _tavily_search(f"trending {query}", max_results=5,
search_depth="basic", include_images=True))
@acrux.tool
async def get_todays_date() -> str:
"""Quick tool to get today's date.
Args: None
"""
return datetime.now().strftime("%Y-%m-%d")
async def main() -> None:
async with AcruxCore() as hub:
results = await hub.tools.sync(
[finance_research, advanced_research, basic_research, get_todays_date]
)
for fn, r in zip([finance_research, advanced_research, basic_research, get_todays_date], results):
print(f"{fn.__name__}: tool_id={r.tool_id} v{r.version_number} committed={r.committed}")
if __name__ == "__main__":
asyncio.run(main())
finance_research: tool_id=c6ffbbff-7e5f-4e6e-acbe-1fd1a027632f v2 committed=True
advanced_research: tool_id=bcf7f63f-7134-412b-8f16-5f745f077133 v1 committed=True
basic_research: tool_id=ab20959a-2651-4779-86f8-0714c967798e v1 committed=True
get_todays_date: tool_id=d0a800d5-a484-4d4f-a9e2-05a715775682 v2 committed=True
finance_research and get_todays_date came back as v2: this team's catalog already had
a v1 for both, created by curl in Build a ReAct agent, with a plainer
hand-written description. tools.sync() is idempotent per name — it found the existing tools
and committed a new version carrying the source's real docstring, exactly the "code supersedes
a dashboard/API version" behavior the SDK documents. Open Gateway → Tools → finance_research
and both versions are visible, v1 tagged api and v2 tagged code:

All four now appear in the catalog:

4. Create the router and subagent prompts over the API
Four prompts, all created by curl: the router, and the three subagents' own system prompts,
quoted from agents/supervisor/supervisor_context.py — none collapsed into another, since
their tool lists overlapping (finance_research_agent and writing_agent both use
basic_research) doesn't make their prompts the same agent.
The router. The source's real supervisor prompt describes the three agents and a
ROUTE_TO:/COMPLETE text protocol for a full multi-hop loop. Since this page reproduces one
routing decision, not the loop, the version below keeps the source's own framing and agent
descriptions verbatim and drops only the ROUTE_TO:/COMPLETE protocol text — that part is
replaced by response_format at call time (Step 5), not by anything stored on this prompt.
Each prompt is created in two calls: first the shell (POST /prompts, name + description only),
then a version (POST /prompts/:id/versions) with the actual messages and model. See
Store prompts and tools via the API
for a deeper walkthrough of this pattern.
- curl
- Python (SDK)
- Node (SDK)
curl -X POST "$ACRUXCORE_BASE_URL/prompts" \
-H "Authorization: Bearer $ACRUXCORE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"content-supervisor","description":"Classifies an incoming content request and routes it to one of three specialist subagents."}'
curl -X POST "$ACRUXCORE_BASE_URL/prompts/2963439b-d01b-4a94-8345-9f0e50b7794d/versions" \
-H "Authorization: Bearer $ACRUXCORE_API_KEY" -H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-direct",
"messages": [
{"role":"system","content":"You are the Executive Content Director orchestrating a team of specialized AI agents to produce exceptional content for clients.\n\nAvailable agents:\n- finance_research_agent: Specialized in financial data research and analysis using Yahoo Finance and other financial sources\n- general_research_agent: Expert at comprehensive web research on any topic using advanced search tools\n- writing_agent: Professional content writer that creates final polished content in any format\n\nRead the user'"'"'s request and decide which single agent should handle it next."},
{"role":"user","content":"{{ question }}"}
]
}'
{"id":"163c1c3a-181d-4568-9165-ace51278bb11","promptId":"2963439b-d01b-4a94-8345-9f0e50b7794d","versionNumber":1,"variables":["question"],"model":"claude-haiku-direct","aliases":[{"alias":"production","versionNumber":1},{"alias":"staging","versionNumber":1}]}
claude-haiku-direct is a model registered against a direct Anthropic connection
(POST /gateway/connections with provider: "anthropic", then POST /gateway/models pointing
it at claude-haiku-4-5-20251001) — matching the source's own default,
anthropic:claude-haiku-4-5, across all four prompts.
response_format requires a direct connectionThe gateway translates response_format into a forced tool call for direct Anthropic connections
and passes it through natively for direct OpenAI connections. For openai_compatible connections
(e.g. OpenRouter), the gateway passes response_format through to the upstream as-is — whether
the upstream honors it is outside the gateway's control. If the router in Step 5 returns
free-text instead of JSON, your connection type is the first thing to check.
The three subagents, each with its own prompt name, its own real system prompt, and the
tool ids tools.sync() returned above:
curl -X POST "$ACRUXCORE_BASE_URL/prompts" -H "Authorization: Bearer $ACRUXCORE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"finance-research-agent","description":"Finance research subagent: Yahoo Finance news plus quick web lookups, for the content supervisor."}'
curl -X POST "$ACRUXCORE_BASE_URL/prompts/a672652c-8ef8-49ac-b674-b4a38bb6d8dd/versions" \
-H "Authorization: Bearer $ACRUXCORE_API_KEY" -H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-direct",
"messages": [
{"role":"system","content":"You are an expert finance research assistant for a digital content agency.\nYou have access to the following tools: finance_research, basic_research, and get_todays_date. \nFirst get today'"'"'s date then continue. \nThe finance_research tool is used to search for financial data and news from Yahoo Finance. \nThe basic_research tool is used to search for general information. \nThe get_todays_date tool is used to get today'"'"'s date. \nWhen you are done with your research, return the research to the supervisor agent."},
{"role":"user","content":"{{ task }}"}
]
}'
{"id":"6bc66e79-5876-465a-a50f-4f138da54783","promptId":"a672652c-8ef8-49ac-b674-b4a38bb6d8dd","versionNumber":1,"variables":["task"],"model":"claude-haiku-direct","aliases":[{"alias":"production","versionNumber":1},{"alias":"staging","versionNumber":1}]}
Then connect its three tools. Bindings live on the prompt, not on a version, so this is
one PUT per tool with nothing to commit afterwards:
for TOOL in c6ffbbff-7e5f-4e6e-acbe-1fd1a027632f ab20959a-2651-4779-86f8-0714c967798e d0a800d5-a484-4d4f-a9e2-05a715775682; do
curl -X PUT "$ACRUXCORE_BASE_URL/prompts/a672652c-8ef8-49ac-b674-b4a38bb6d8dd/tools/$TOOL" \
-H "Authorization: Bearer $ACRUXCORE_API_KEY" -H "Content-Type: application/json" \
-d '{"tool_alias":"production"}'
done
The other two subagents follow the exact same shape — create the prompt shell, commit a version with the system and user prompts, then connect its tools. You can do this from the dashboard (Prompts → New prompt, the Editor tab to commit a version, the Tools tab to connect the tools) or repeat the same curl calls. Here is what each one needs:
general-research-agent — tools: advanced_research + get_todays_date
You are an expert general research agent. You have access to the following tools: advanced_research and get_todays_date. First get today's date then continue to use the advanced_research tool to search for general information on the topic you are given to research, when your done you return the research to the supervisor agent. YOU MUST USE THE ADVANCED_RESEARCH TOOL TO GET THE INFORMATION YOU NEED
writing-agent — tools: basic_research + get_todays_date
You are an expert writing assistant. Your primary responsibility is to help draft, edit, and improve written content to ensure clarity, correctness, and engagement. You are strictly supposed to take in the content you are given and write the final content based on the requested format for the user, then return the final content to the supervisor agent.
Both use {{ task }} as the user prompt variable, same as the finance agent.
Same shape via the SDK. hub.prompts.create() creates the shell, hub.prompts.commit_version() stores the messages, and hub.prompts.set_tool_binding() connects each tool. The router prompt needs no tools; each subagent prompt binds its own:
from acruxcore import AcruxCore
async with AcruxCore() as hub:
# Router prompt (no tools)
router = await hub.prompts.create(
"content-supervisor",
description="Classifies an incoming content request and routes it to one of three specialist subagents.",
)
await hub.prompts.commit_version(
router.id,
model="claude-haiku-direct",
messages=[
{"role": "system", "content": "You are the Executive Content Director orchestrating a team of specialized AI agents to produce exceptional content for clients.\n\nAvailable agents:\n- finance_research_agent: Specialized in financial data research and analysis using Yahoo Finance and other financial sources\n- general_research_agent: Expert at comprehensive web research on any topic using advanced search tools\n- writing_agent: Professional content writer that creates final polished content in any format\n\nRead the user's request and decide which single agent should handle it next."},
{"role": "user", "content": "{{ question }}"},
],
)
# Finance research subagent
finance = await hub.prompts.create(
"finance-research-agent",
description="Finance research subagent: Yahoo Finance news plus quick web lookups, for the content supervisor.",
)
await hub.prompts.commit_version(
finance.id,
model="claude-haiku-direct",
messages=[
{"role": "system", "content": "You are an expert finance research assistant for a digital content agency.\nYou have access to the following tools: finance_research, basic_research, and get_todays_date. \nFirst get today's date then continue. \nThe finance_research tool is used to search for financial data and news from Yahoo Finance. \nThe basic_research tool is used to search for general information. \nThe get_todays_date tool is used to get today's date. \nWhen you are done with your research, return the research to the supervisor agent."},
{"role": "user", "content": "{{ task }}"},
],
)
for tool_id in (
"c6ffbbff-7e5f-4e6e-acbe-1fd1a027632f",
"ab20959a-2651-4779-86f8-0714c967798e",
"d0a800d5-a484-4d4f-a9e2-05a715775682",
):
await hub.prompts.set_tool_binding(finance.id, tool_id, tool_alias="production")
# Repeat for general-research-agent and writing-agent...
Full script (all four prompts, not just the two shown): setup_prompts.py.
The other two subagents follow the exact same shape — create the prompt shell, then commit a
version with the system prompt, user prompt, and tool ids. Both use {{ task }} as the user
prompt variable, same as the finance agent.
Same shape via the Node SDK. hub.prompts.create() creates the shell, hub.prompts.commitVersion() stores the messages, and hub.prompts.setToolBinding() connects each tool:
import { acruxcore } from '@acruxcoreai/sdk';
const hub = new acruxcore();
// Router prompt (no tools)
const router = await hub.prompts.create({
name: "content-supervisor",
description: "Classifies an incoming content request and routes it to one of three specialist subagents.",
});
await hub.prompts.commitVersion(router.id, {
model: "claude-haiku-direct",
messages: [
{ role: "system", content: "You are the Executive Content Director orchestrating a team of specialized AI agents to produce exceptional content for clients.\n\nAvailable agents:\n- finance_research_agent: Specialized in financial data research and analysis using Yahoo Finance and other financial sources\n- general_research_agent: Expert at comprehensive web research on any topic using advanced search tools\n- writing_agent: Professional content writer that creates final polished content in any format\n\nRead the user's request and decide which single agent should handle it next." },
{ role: "user", content: "{{ question }}" },
],
});
// Finance research subagent
const finance = await hub.prompts.create({
name: "finance-research-agent",
description: "Finance research subagent: Yahoo Finance news plus quick web lookups, for the content supervisor.",
});
await hub.prompts.commitVersion(finance.id, {
model: "claude-haiku-direct",
messages: [
{ role: "system", content: "You are an expert finance research assistant for a digital content agency.\nYou have access to the following tools: finance_research, basic_research, and get_todays_date. \nFirst get today's date then continue. \nThe finance_research tool is used to search for financial data and news from Yahoo Finance. \nThe basic_research tool is used to search for general information. \nThe get_todays_date tool is used to get today's date. \nWhen you are done with your research, return the research to the supervisor agent." },
{ role: "user", content: "{{ task }}" },
],
});
for (const toolId of [
"c6ffbbff-7e5f-4e6e-acbe-1fd1a027632f",
"ab20959a-2651-4779-86f8-0714c967798e",
"d0a800d5-a484-4d4f-a9e2-05a715775682",
]) {
await hub.prompts.setToolBinding(finance.id, toolId, { toolAlias: "production" });
}
// Repeat for general-research-agent and writing-agent...
The other two subagents follow the exact same shape — create the prompt shell, then commit a
version with the system prompt, user prompt, and tool ids. Both use {{ task }} as the user
prompt variable, same as the finance agent.
5. Run the two-step router → subagent flow
The flow has two steps:
- Classify. Render the router prompt and call the gateway with
response_formatset to a typed JSON schema —{"route_to": "finance_research_agent" | "general_research_agent" | "writing_agent"}. The model returns a structured answer like{"route_to": "finance_research_agent"}. This call carries no tools (response_formatandtoolsare mutually exclusive on one request). Capture the trace id fromx-gateway-trace-id. - Dispatch. Render the subagent prompt the router picked, and run its tools via
runToolLoop()/run_tool_loop()(curl loops by hand), passing that same trace id so the hand-off lands in one trace instead of two.
Run each script twice, with two genuinely different questions, to prove the routing is real:
./supervisor_flow.sh "Research Tesla (TSLA) latest stock news and tell me if investors should be worried."
./supervisor_flow.sh "What are the biggest trends in sustainable packaging for consumer goods in 2026?"
The first is a finance question; the second is a general-research question. If routing were hardcoded, both would land on the same subagent — they don't.
- curl
- Python
- Node
The full script threads one trace across the router call and the subagent's tool loop — see supervisor_flow.sh on GitHub for the complete source.
./supervisor_flow.sh "Research Tesla (TSLA) latest stock news and tell me if investors should be worried."
Question: Research Tesla (TSLA) latest stock news and tell me if investors should be worried.
Step A -- routed to: finance_research_agent (trace ed61263e-3b02-4cd3-8b9f-5c1c00080aca)
-> get_todays_date({})
2026-08-01
-> finance_research({"ticker_symbol":"TSLA"})
[{"title":"SpaceX stock hits new closing low in rocky week ahead of earnings"},{"title":"Tesla reportedly considering a spin off of its China business"},{"title":"Tesla Rival BYD Ramping Up Sales On O
Step B -- finance_research_agent: Based on the latest financial news for Tesla (TSLA) as of August 1, 2026, here's my analysis:
### Key Findings:
- **Tesla considering a spin-off of its China business** - potentially significant restructuring news
- **BYD ramping up overseas sales** - intensifying competitive pressure in the EV market
### Should Investors Be Worried?
Mixed signals, cautious approach recommended. Monitor earnings reports and official statements
about the China spin-off, and watch for the impact of BYD's overseas growth on Tesla's market
share. Not necessarily a red flag for panic selling at this point.
(2 model turn(s), trace ed61263e-3b02-4cd3-8b9f-5c1c00080aca)
./supervisor_flow.sh "What are the biggest trends in sustainable packaging for consumer goods in 2026?"
Question: What are the biggest trends in sustainable packaging for consumer goods in 2026?
Step A -- routed to: general_research_agent (trace 60754ee4-221d-4a53-94a3-09ccdff534e7)
-> get_todays_date({})
2026-08-01
-> advanced_research({"query":"biggest trends sustainable packaging consumer goods 2026"})
[{"title":"Food packaging trends 2026: Sustainability, digital innovation & consumer-centric solutions","url":"https://www.foodingredientsfirst.com/news/food-packaging-trends-sustainability-digital-in
Step B -- general_research_agent: Perfect! I've completed my research on the biggest trends in
sustainable packaging for consumer goods in 2026:
1. Food Packaging & Sustainability Focus, 2. Digital Innovation Integration, 3. Eco-Friendly
Materials Leadership, 4. Consumer-Centric Design, 5. Circular Economy Models, 6. Market Growth,
7. Compliance & Regulations.
(2 model turn(s), trace 60754ee4-221d-4a53-94a3-09ccdff534e7)
Same script, different question — a finance ticker question routed to finance_research_agent
and called the real Yahoo Finance tool; a general trends question routed to
general_research_agent and called the real Tavily-backed advanced_research. Two different
subagents, two different tool sets, one classification decision each.
run_tool_loop() drives Step B; Step A stays a plain requests.post even though
response_format is now in the SDK's chat()/run_tool_loop() (see the Medical-Information
QA Agent tutorial) — it's a single standalone call
with no loop, so the raw POST shows the wire shape rather than reaching for an SDK method
built for multi-round tool loops. tools= passes the same decorated functions Step 3
already synced, with sync=False since nothing has changed since that sync.
The full script threads one trace across the router call and the subagent's
run_tool_loop() — see supervisor_flow.py on GitHub for the complete source.
python supervisor_flow.py "Research Tesla's (TSLA) latest stock news and tell me if investors should be worried."
Question: Research Tesla's (TSLA) latest stock news and tell me if investors should be worried.
Step A -- routed to: finance_research_agent (trace b1c11786-175b-4ddb-953b-d38892e53481)
Step B -- finance_research_agent: Based on my research of Tesla (TSLA) as of August 1, 2026, here's what investors should know:
**Current Performance Concerns:**
- Tesla shares are down approximately 1% over the past year
- The stock is down 30% year-to-date, with a dramatic single-day drop of 14.5% on July 23rd
**Should Investors Be Worried?**
Mixed signals. Reasons for caution: the 30% YTD decline and the sharp single-day drop suggest a
recent negative catalyst. Reasons to stay patient: Jim Cramer continues to express belief in
Tesla and Elon Musk despite the weak share performance, suggesting some analysts still see
long-term value.
**Bottom Line:** Monitor the situation but don't necessarily panic — understanding *why* the
stock dropped so sharply would determine if this is a temporary correction or something deeper.
(2 model turn(s), trace b1c11786-175b-4ddb-953b-d38892e53481)
python supervisor_flow.py "What are the biggest trends in sustainable packaging for consumer goods in 2026?"
Question: What are the biggest trends in sustainable packaging for consumer goods in 2026?
Step A -- routed to: general_research_agent (trace ece520e8-66c8-400c-824c-d7b16b7468f7)
Step B -- general_research_agent: Perfect! I've completed my research on the biggest trends in
sustainable packaging for consumer goods in 2026:
1. Substantiated Sustainability, 2. Circularity as the Default Expectation, 3. Paper & Paperboard
Dominance (38-41% of the market), 4. Digital-Enhanced Smart Packaging, 5. Recycled Content as
Trust Signal, 6. Design Efficiency & Minimalism, 7. Reusable & Refill Formats, 8. Circular Luxury,
9. Transparency & Clear Disposal Guidance, 10. Conditional Compostables Framework.
Global sustainable packaging market: USD 319.3-399.97 billion in 2026, 5.8-6.7% CAGR through
2035-2036.
(2 model turn(s), trace ece520e8-66c8-400c-824c-d7b16b7468f7)
Same script, same tool functions from Step 3 — the only thing that changed between the two runs is which question the router read.
Same shape, runToolLoop() instead of run_tool_loop(). Since Node's tool() needs a hand-written
JSON Schema rather than deriving one from a docstring, this tab passes the four tools as
toolRefs (resolved from the catalog Step 3 already populated) plus a clientTools map holding
all four functions — one map covers every route, because toolRefs decides which subset the
model is offered and an entry the route does not bind is never called. It @langchain/tavily's real TavilySearch class for advanced_research/basic_research —
the same wrapper Build a configurable ReAct agent uses.
finance_research here reads Nasdaq's public per-symbol RSS feed instead of Yahoo Finance
directly: the same real, environment-specific gap
Build a ReAct agent's Node tab hit — this environment's fetch cannot
reach Yahoo's edge (ETIMEDOUT/ENETUNREACH), even though curl and Python reach it fine moments
apart. Real, live headline data either way, just a different real source for that one tool call.
The full script threads one trace across the router call and the subagent's
runToolLoop() — see supervisor_flow.mjs on GitHub for the complete source.
node supervisor_flow.mjs "Research Tesla's (TSLA) latest stock news and tell me if investors should be worried."
Question: Research Tesla's (TSLA) latest stock news and tell me if investors should be worried.
Step A -- routed to: finance_research_agent (trace 9a9623b9-e0da-4fe9-9fb3-2204c6d38eb8)
Step B -- finance_research_agent: Based on my research of Tesla (TSLA) as of August 1, 2026, here's what the latest stock news shows:
**Positive Development:** Tesla's $99-a-month Full Self-Driving (FSD) subscription plan is on
pace to generate $1.8 billion annually.
**My Assessment:** Not necessarily worrying — mixed signals. Tesla is successfully monetizing
its FSD technology, and the broader market sentiment appears positive. Recommend monitoring
quarterly earnings, FSD adoption rates, and delivery numbers for a more complete picture.
(2 model turn(s), trace 9a9623b9-e0da-4fe9-9fb3-2204c6d38eb8)
node supervisor_flow.mjs "What are the biggest trends in sustainable packaging for consumer goods in 2026?"
Question: What are the biggest trends in sustainable packaging for consumer goods in 2026?
Step A -- routed to: general_research_agent (trace f491aa68-3862-4823-917d-4ab95feae80a)
Step B -- general_research_agent: Perfect! I've gathered research on the biggest trends in
sustainable packaging for consumer goods in 2026:
1. Advanced Sustainable Materials, 2. Digital Innovation & Smart Packaging, 3. Consumer-Centric
Design Solutions, 4. Circular Economy Principles, 5. Regulatory Compliance & Standards,
6. Functional Sustainability Features, 7. Supply Chain Transparency, 8. Active & Intelligent
Packaging, 9. Global Material Innovations, 10. Cost-Effective Sustainability.
(2 model turn(s), trace f491aa68-3862-4823-917d-4ab95feae80a)
6. Inspect the trace
Open Observability → Traces and the general-research run above shows up as one trace
with 5 spans: the router's llm call, the subagent's own llm call, the
get_todays_date and advanced_research tool calls in between, and a final llm call with
the answer — all on claude-haiku-4-5-20251001, the model both the router prompt and the
subagent prompts are bound to:

Expanding the first LLM span — the router call — shows the real input (the supervisor system
prompt plus the question) and the real output: a bare JSON object, {"route_to": "general_research_agent"}, no free text around it, because response_format constrained it:

And the advanced_research tool span shows the real query the subagent chose and the real
Tavily results it got back — proof the hand-off carried the subagent's own tools into the same
trace the router opened:

Two model calls, two different prompts, four spans of real tool and model activity between them — one trace, exactly as the classification note at the top promised.
What's next
- Build a configurable ReAct agent — more on the
basic_research/advanced_researchTavily split this page's subagents reuse. - Build a ReAct agent — the baseline
finance_research+get_todays_datetool pair, without a gateway or a router in front of them. - API details: see Prompts, Tools, and Traces in the API Reference.