On this article, you’ll learn to construct a multi-agent AI analysis assistant utilizing the OpenAI Brokers SDK, the GPT-5.4 mini mannequin, and the Olostep Internet API, together with wire collectively a supervisor agent, specialist sub-agents, and reside internet instruments to provide structured, source-grounded analysis reviews.
Subjects we are going to cowl embrace:
- How one can outline a supervisor agent that orchestrates a decide agent and an analyst agent to progressively collect and consider proof.
- How one can combine Olostep’s Reply, Search, Search-with-Scrape, and Scrape APIs as callable instruments contained in the OpenAI Brokers SDK workflow.
- How one can expose the completed analysis assistant as an interactive internet utility constructed with Reflex, full with PDF export.
How one can Construct a Multi-Agent Analysis Assistant in Python
Introduction
I’ve been experimenting with the OpenAI Brokers SDK, and it has rapidly turn into one in every of my favourite methods to construct agentic AI functions. What stood out to me is how easy it’s to create a multi-agent workflow: you outline a supervisor agent, join it with specialist sub-agents and instruments, and let it determine full the duty.
The supervisor agent can delegate work to different brokers, name instruments immediately, and coordinate the general analysis course of. This makes it potential to construct AI functions that do greater than generate textual content — they will search the net, collect info, arrange findings, and produce grounded outputs.
On this information, we are going to construct a multi-agent AI analysis assistant utilizing the OpenAI Brokers SDK, the GPT-5.4 mini mannequin, and the Olostep Internet API. The assistant will generate a structured analysis report that’s grounded in internet knowledge, straightforward to learn, and produced in just some seconds.
The information additionally consists of the total code, an internet app, and a hyperlink to the deployed model so you possibly can take a look at the system your self. By the top, you’ll perceive how a number of brokers can work collectively to create a sensible analysis assistant from scratch.
1. Set Up the Setting
Earlier than constructing the multi-agent analysis assistant, we have to arrange the Python atmosphere and configure the required API keys.
We’ll use 4 primary packages:
- openai-agents for constructing and working the multi-agent workflow
- olostep for accessing reside internet knowledge
- pydantic for outlining structured outputs
- python-dotenv for loading API keys from a .env file
Run the next command to put in the required packages:
|
pip set up –q –U openai–brokers olostep python–dotenv pydantic |
Subsequent, create a .env file in your undertaking listing. This file will retailer your API keys securely, so you do not want to hardcode them inside your pocket book or utility.
|
OPENAI_API_KEY=your_openai_api_key OLOSTEP_API_KEY=your_olostep_api_key |
You possibly can create your OpenAI API key from the OpenAI Platform. Register to your OpenAI account, go to the API keys part, and generate a brand new key for this undertaking. Be sure your OpenAI API account has billing enabled and not less than $5 in credit out there earlier than working the examples. You might also want to finish account verification to entry the newest fashions.
For Olostep, create a free account from the Olostep web site and generate an API key out of your dashboard. The free plan consists of 500 profitable requests with no bank card required, which is sufficient to take a look at the analysis assistant on this information.
As soon as your keys are prepared, we are going to begin in a Jupyter Pocket book by importing the required libraries and loading the atmosphere variables. This setup prepares the pocket book to work with OpenAI, Olostep, structured outputs, and tracing.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import json import os from datetime import datetime from typing import Any  from dotenv import load_dotenv from IPython.show import Markdown, show from olostep import Olostep from pydantic import BaseModel, Area  from brokers import (     Agent,     Runner,     custom_span,     flush_traces,     function_tool,     gen_trace_id,     hint, )  load_dotenv()  OPENAI_API_KEY = os.getenv(“OPENAI_API_KEY”) OLOSTEP_API_KEY = os.getenv(“OLOSTEP_API_KEY”) |
2. Take a look at Olostep Search with Scraping
Earlier than constructing the total multi-agent workflow, it’s helpful to check whether or not Olostep can search the net and scrape the returned pages efficiently. This step confirms that your API secret is working and that the search outcomes embrace sufficient web page content material for downstream evaluation.
The Olostep Search API is very helpful as a result of it could actually return search outcomes with a built-in scraping choice. As an alternative of solely receiving web page titles, snippets, and hyperlinks, you possibly can ask Olostep to scrape the returned URLs and supply the extracted content material in codecs equivalent to Markdown.
This implies the agent can work with high-quality web page content material immediately, relatively than relying solely on search snippets. It additionally saves time as a result of you do not want to construct a separate search-and-scrape pipeline your self.
|
consumer = Olostep(api_key=OLOSTEP_API_KEY) Â search = consumer.searches.create( Â Â Â Â question=“What are an important latest developments in AI brokers for enterprise analysis?”, Â Â Â Â restrict=5, Â Â Â Â scrape_options={“codecs”: [“markdown”], “timeout”: 25}, ) Â for hyperlink in search.hyperlinks: Â Â Â Â print(hyperlink[“url”], “-“, len(hyperlink.get(“markdown_content”) or “”), “chars”) |
This tells Olostep to scrape every returned web page and supply the extracted content material in Markdown format. Markdown is helpful as a result of it retains the content material readable whereas eradicating pointless web page muddle. The timeout worth provides Olostep sufficient time to fetch and course of every web page.
After the search is full, we loop via the returned hyperlinks and print every URL together with the variety of characters extracted from the web page.
3. Add Helper Capabilities
Earlier than creating the brokers and instruments, we have to add just a few helper features. These utilities preserve the remainder of the code cleaner and make the workflow simpler to debug.
The helper features will deal with six issues:
- Verify whether or not the Olostep API secret is out there
- Create a reusable Olostep consumer
- Convert SDK responses into commonplace Python dictionaries
- Compress giant JSON outputs so they’re simpler to examine
- Add the present date and 12 months as context for the brokers
- Normalize search outcomes into an easier format for the brokers
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
class OlostepError(RuntimeError):     “”“Raised when an Olostep SDK request fails.”“”  def require_olostep_key() -> str:     if not OLOSTEP_API_KEY:         increase OlostepError(             “OLOSTEP_API_KEY isn’t set. Add it to .env and rerun the setup cell.”         )     return OLOSTEP_API_KEY  def get_olostep_client() -> Olostep:     return Olostep(api_key=require_olostep_key())  def sdk_result_to_dict(end result: Any) -> dict[str, Any]:     if hasattr(end result, “model_dump”):         return end result.model_dump()     if hasattr(end result, “__dict__”):         return {             key: worth for key, worth in vars(end result).gadgets() if not key.startswith(“_”)         }     return {“worth”: str(end result)}  def compact_json(knowledge: Any, max_chars: int = 8000) -> str:     textual content = json.dumps(knowledge, ensure_ascii=False, indent=2, default=str)     if len(textual content) <= max_chars:         return textual content     return textual content[:max_chars] + “n… [truncated]”  def current_date_context() -> str:     return datetime.now().strftime(“%B %d, %Y”)  def current_year_context() -> str:     return str(datetime.now().12 months)  def normalize_search_links(     hyperlinks: listing[dict[str, Any]], restrict: int = 8 ) -> listing[dict[str, Any]]:     rows = []     for hyperlink in hyperlinks[:limit]:         markdown = hyperlink.get(“markdown_content”) or “”         rows.append(             {                 “title”: hyperlink.get(“title”) or “Untitled”,                 “url”: hyperlink.get(“url”) or “”,                 “description”: hyperlink.get(“description”) or “”,                 “markdown_chars”: len(markdown),                 “markdown_preview”: markdown[:1500] if markdown else “”,             }         )     return rows |
4. Outline Structured Output Fashions
Subsequent, outline the structured outputs that the brokers will return. These fashions make the workflow extra dependable as a result of every agent should return info in a constant format.
The decide agent makes use of the Judgment mannequin to determine whether or not the gathered proof is powerful sufficient. The analyst agent makes use of the MarkdownResearchReport mannequin to return the ultimate report as polished Markdown.
|
class Judgment(BaseModel): Â Â Â Â is_good_enough: bool = Area( Â Â Â Â Â Â Â Â description=“Whether or not the reply is enough for the person question, which means rating >= 0.85.” Â Â Â Â ) Â Â Â Â rating: float = Area(ge=0, le=1, description=“High quality rating from 0 to 1.”) Â Â Â Â cause: str = Area(description=“Quick clarification of the choice.”) Â Â Â Â missing_information: listing[str] = Area( Â Â Â Â Â Â Â Â default_factory=listing, description=“Vital gaps to repair.” Â Â Â Â ) Â class MarkdownResearchReport(BaseModel): Â Â Â Â markdown_report: str = Area( Â Â Â Â Â Â Â Â description=“Full Markdown report with polished headings, clear evaluation, reader-friendly construction, and citations.” Â Â Â Â ) |
Judgment works because the quality-control schema. It helps the decide agent determine whether or not the gathered proof is powerful sufficient or whether or not the supervisor agent ought to proceed looking.
MarkdownResearchReport defines the ultimate analysis output. Because the remaining app solely wants the finished report, this mannequin retains a single markdown_report subject as an alternative of additional metadata fields. This makes the output easier and simpler to show within the pocket book, internet app, and PDF export.
5. Create Olostep Device Capabilities
Now create the instruments that the supervisor agent can name in the course of the analysis course of. These instruments wrap Olostep’s Reply API, Search API, Search with Scrape, and Scrape API.
Every device consists of tracing spans so you possibly can examine what occurred throughout execution within the OpenAI hint viewer. That is helpful for debugging as a result of you possibly can see which device was referred to as, what enter it obtained, and the way the supervisor agent moved via the workflow.
Reply Question Device
This device asks Olostep for a fast reply to the person’s analysis query. It’s used as step one within the workflow earlier than deciding whether or not extra analysis is required.
|
@function_tool async def answer_query(question: str) -> str: Â Â Â Â “”“Reply a natural-language analysis question utilizing Olostep Reply API.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span(“olostep.answer_query”, {“question”: question}): Â Â Â Â Â Â Â Â Â Â Â Â end result = get_olostep_client().solutions.create(activity=question) Â Â Â Â Â Â Â Â Â Â Â Â return compact_json(sdk_result_to_dict(end result)) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Reply API failed: {exc}”) from exc |
Search Internet Device
This device runs an ordinary internet search and returns normalized outcomes. It’s helpful when the assistant wants to find further sources earlier than scraping particular pages.
The output is deliberately compact. As an alternative of returning the total uncooked API response, the device returns the question and a cleaned listing of search outcomes. This makes the response simpler for the supervisor agent to learn and reduces pointless context.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@function_tool async def search_web(question: str, restrict: int = 8) -> str: Â Â Â Â “”“Search the net utilizing Olostep Search and return normalized outcomes.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span(“olostep.search_web”, {“question”: question, “restrict”: restrict}): Â Â Â Â Â Â Â Â Â Â Â Â search = get_olostep_client().searches.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â question=question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge = sdk_result_to_dict(search) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “outcomes”: normalize_search_links( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge.get(“hyperlinks”, []), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Search API failed: {exc}”) from exc |
Search with Scrape Device
This device searches the net and scrapes the returned pages in a single step. It provides the analysis assistant richer proof than search snippets alone.
This is likely one of the most necessary instruments within the undertaking as a result of it lets the agent retrieve each hyperlinks and web page content material from a single name. As an alternative of first looking the net, choosing URLs, after which scraping every one individually, the device can return usable Markdown content material immediately from the found pages.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
@function_tool async def search_with_scrape(question: str, restrict: int = 5) -> str: Â Â Â Â “”“Search the net and scrape every returned hyperlink utilizing Olostep Search with Scrape.”“” Â Â Â Â scrape_options = { Â Â Â Â Â Â Â Â “codecs”: [“markdown”], Â Â Â Â Â Â Â Â “timeout”: 25, Â Â Â Â } Â Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span( Â Â Â Â Â Â Â Â Â Â Â Â “olostep.search_with_scrape”, Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “restrict”: restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “scrape_options”: scrape_options, Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â ): Â Â Â Â Â Â Â Â Â Â Â Â search = get_olostep_client().searches.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â question=question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scrape_options=scrape_options, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge = sdk_result_to_dict(search) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “outcomes”: normalize_search_links( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge.get(“hyperlinks”, []), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â max_chars=12000, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Search with Scrape failed: {exc}”) from exc |
Scrape URL Device
This device scrapes a single URL and returns compact web page content material. The supervisor agent makes use of it when it wants deeper proof from chosen sources.
For instance, the supervisor could first use search_web to search out related pages, then use scrape_url to retrieve the total content material from essentially the most helpful hyperlinks.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@function_tool async def scrape_url(url: str) -> str: Â Â Â Â “”“Scrape one URL with Olostep and return compact web page content material.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span( Â Â Â Â Â Â Â Â Â Â Â Â “olostep.scrape_url”, Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “url”: url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “codecs”: [“markdown”], Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â ): Â Â Â Â Â Â Â Â Â Â Â Â scrape = get_olostep_client().scrapes.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â url=url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â codecs=[“markdown”], Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “url”: url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “scrape”: sdk_result_to_dict(scrape), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â max_chars=10000, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Scrape API failed: {exc}”) from exc |
These instruments give the supervisor agent other ways to assemble proof. It might probably begin with a fast reply, seek for extra sources, use Search with Scrape for richer context, or scrape a particular URL when it wants extra element.
6. Construct the Specialist Brokers
The workflow makes use of two specialist brokers: a decide agent and an analyst agent.
The decide agent checks whether or not the gathered proof is powerful sufficient to reply the person’s query. The analyst agent then turns the accredited proof into a refined Markdown analysis report.
First, outline the mannequin that each specialist brokers will use:
Decide Agent
The decide agent evaluates reply high quality. It checks whether or not the reply is restricted, present, source-backed, and full sufficient to cease the analysis course of.
That is necessary as a result of the supervisor agent shouldn’t produce a remaining report from weak proof. If the reply is imprecise, outdated, unsupported, or lacking key particulars, the decide agent will reject it and the supervisor agent can proceed looking.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
judge_agent = Agent( Â Â Â Â identify=“Decide agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â “You decide whether or not the supplied reply is nice sufficient for the unique analysis query. “ Â Â Â Â Â Â Â Â “Reward direct, particular, source-backed solutions. Reject imprecise, stale, or unsupported solutions. “ Â Â Â Â Â Â Â Â “Be strict: is_good_enough have to be true solely when rating >= 0.85 and the proof immediately solutions “ Â Â Â Â Â Â Â Â “the query with concrete supply content material, topic-specific element, and applicable recency. “ Â Â Â Â Â Â Â Â “For present occasions, product standing, insurance policies, pricing, or factual claims that will change, require latest “ Â Â Â Â Â Â Â Â “major or extremely respected sources. Don’t mark proof enough if any vital hole stays. “ Â Â Â Â Â Â Â Â “Calibrate scores this fashion: 0.85-1.0 means enough to cease with robust supply help and no vital gaps; “ Â Â Â Â Â Â Â Â “0.75-0.84 means robust however nonetheless lacking one necessary supply, element, recency verify, or protection space; “ Â Â Â Â Â Â Â Â “0.50-0.74 means related partial proof that wants extra analysis; 0.25-0.49 means skinny, imprecise, stale, “ Â Â Â Â Â Â Â Â “or weakly associated proof; beneath 0.25 is just for empty, unusable, or principally unrelated proof. “ Â Â Â Â Â Â Â Â “Don’t mark proof enough simply because it’s believable or directionally appropriate. “ Â Â Â Â Â Â Â Â “Return solely the structured judgment.” Â Â Â Â ), Â Â Â Â output_type=Judgment, ) |
The decide agent returns a Judgment object. This consists of whether or not the proof is nice sufficient, a top quality rating, a brief cause, and any lacking info that also must be addressed.
Analyst Agent
The analyst agent writes the ultimate Markdown report. It turns the gathered proof right into a readable analysis transient with clear sections, supply notes, and references.
This agent is accountable for making the output helpful for knowledgeable reader. As an alternative of merely summarizing uncooked device outputs, it organizes the findings into a whole report that explains the subject, highlights an important proof, and cites the sources used.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
analyst_agent = Agent( Â Â Â Â identify=“Analyst agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â “You write a correct Markdown analysis report from the proof. “ Â Â Â Â Â Â Â Â “Write for knowledgeable reader who needs a transparent, polished analysis transient on any subject. “ Â Â Â Â Â Â Â Â “Adapt the report back to the person’s query. The markdown_report have to be substantial, straightforward to scan, and use these basic sections solely: “ Â Â Â Â Â Â Â Â “Government Abstract, Key Findings, Context, Proof Overview, Detailed Evaluation, Implications, Supply Notes, and References. “ Â Â Â Â Â Â Â Â “If the subject is event-driven, embrace timeline particulars inside Context or Detailed Evaluation as an alternative of including a separate Timeline part. “ Â Â Â Â Â Â Â Â “If the subject is comparative, embrace a compact comparability desk inside Detailed Evaluation. “ Â Â Â Â Â Â Â Â “Don’t embrace sections titled Limitations, Subsequent Steps, Suggestions, or Motion Objects. “ Â Â Â Â Â Â Â Â “Keep away from naked caveats like ‘I relied on…’. As an alternative, combine supply high quality naturally in Supply Notes. “ Â Â Â Â Â Â Â Â “Use quick paragraphs, bullets the place useful, and citations as Markdown hyperlinks or URL bullets. “ Â Â Â Â Â Â Â Â “Add sufficient context {that a} non-expert reader understands the difficulty, why it issues, and what proof helps it. “ Â Â Â Â Â Â Â Â “Don’t use emoji, return-arrow symbols, backlink icons, or ornamental icons wherever within the report. “ Â Â Â Â Â Â Â Â “In References, listing solely plain Markdown bullets or numbered gadgets with the supply identify and URL. “ Â Â Â Â Â Â Â Â “Return solely the structured report.” Â Â Â Â ), Â Â Â Â output_type=MarkdownResearchReport, ) |
The analyst agent returns a MarkdownResearchReport object with one subject: markdown_report. This retains the ultimate output easy as a result of the entire title, abstract, findings, evaluation, supply notes, and references are all included contained in the Markdown report itself.
7. Create the Supervisor Agent
The supervisor agent is the orchestrator. It controls the total analysis workflow and decides which device or specialist agent ought to run subsequent.
The workflow follows this sample:
- Begin with a fast reply utilizing the Olostep Reply API
- Ask the decide agent whether or not the reply is nice sufficient
- If not, run Search with Scrape for stronger proof
- Ask the decide agent once more
- If the proof remains to be weak, run focused searches and scrape essentially the most related pages
- Ask the analyst agent to jot down the ultimate report
First, convert the decide and analyst brokers into instruments. This enables the supervisor agent to name them in the course of the workflow.
|
judge_tool = judge_agent.as_tool( Â Â Â Â tool_name=“judge_answer_quality”, Â Â Â Â tool_description=“Decide whether or not a solution or proof is nice sufficient for the unique analysis query.”, ) Â analyst_tool = analyst_agent.as_tool( Â Â Â Â tool_name=“write_markdown_research_report”, Â Â Â Â tool_description=“Write the ultimate structured Markdown analysis report from the gathered proof.”, ) |
Now outline the supervisor agent. This agent doesn’t reply from reminiscence. As an alternative, it follows a transparent analysis course of: reply, decide, search, decide once more, scrape if wanted, after which write the ultimate report.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
manager_agent = Agent( Â Â Â Â identify=“Supervisor analysis agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â f“Present date: {current_date_context()}n” Â Â Â Â Â Â Â Â f“Present 12 months: {current_year_context()}nn” Â Â Â Â Â Â Â Â “You’re the orchestrator for a multi-agent analysis assistant. You could handle the workflow, “ Â Â Â Â Â Â Â Â “not reply from your individual reminiscence. Comply with this coverage precisely:n” Â Â Â Â Â Â Â Â “1. All the time name answer_query first to get a easy preliminary reply for the person’s query.n” Â Â Â Â Â Â Â Â “2. Instantly name judge_answer_quality on the unique query plus the answer_query end result. “ Â Â Â Â Â Â Â Â “If the decide returns is_good_enough=true and rating >= 0.85, cease researching and name “ Â Â Â Â Â Â Â Â “write_markdown_research_report with the query, reply end result, and judgment.n” Â Â Â Â Â Â Â Â “3. If the primary judgment is weak, name search_with_scrape for the unique query. “ Â Â Â Â Â Â Â Â “Instantly name judge_answer_quality once more on the unique query plus the answer_query end result, “ Â Â Â Â Â Â Â Â “first judgment, and search_with_scrape end result. If this second decide returns is_good_enough=true “ Â Â Â Â Â Â Â Â “and rating >= 0.85, cease researching and name write_markdown_research_report with all proof.n” Â Â Â Â Â Â Â Â “4. If the second judgment remains to be weak, don’t name the decide once more. Run a number of focused “ Â Â Â Â Â Â Â Â “search_web calls first, utilizing the decide’s missing_information to kind the searches. Examine the “ Â Â Â Â Â Â Â Â “search outcomes, select not less than the highest 3 related supply URLs most definitely to reply the lacking “ Â Â Â Â Â Â Â Â “factors, then name scrape_url on every of these prime 3 pages. Scrape greater than 3 provided that clearly wanted.n” Â Â Â Â Â Â Â Â “5. Name write_markdown_research_report precisely as soon as on the finish, utilizing each reply, judgment, “ Â Â Â Â Â Â Â Â “search end result, and scraped web page. The analyst should produce the ultimate MarkdownResearchReport.n” Â Â Â Â Â Â Â Â “6. Return solely the ultimate MarkdownResearchReport. Don’t return an off-the-cuff chat reply, device transcript, or plan.” Â Â Â Â ), Â Â Â Â instruments=[ Â Â Â Â Â Â Â Â answer_query, Â Â Â Â Â Â Â Â judge_tool, Â Â Â Â Â Â Â Â search_with_scrape, Â Â Â Â Â Â Â Â search_web, Â Â Â Â Â Â Â Â scrape_url, Â Â Â Â Â Â Â Â analyst_tool, Â Â Â Â ], Â Â Â Â output_type=MarkdownResearchReport, ) |
The supervisor agent is the core of the system. It decides when the primary reply is sufficient, when extra proof is required, and when to name the analyst agent to provide the ultimate report.
The important thing concept is that the supervisor doesn’t depend on a single device name. It begins with a quick reply, checks high quality, and solely does deeper analysis when wanted. This retains the workflow environment friendly whereas nonetheless permitting the assistant to assemble stronger proof for extra complicated questions.
8. Run the Analysis Assistant with Tracing
The ultimate perform runs the supervisor agent and returns a structured analysis report. It additionally creates an OpenAI hint ID so you possibly can examine the total workflow, together with supervisor choices, specialist agent calls, device utilization, and Olostep spans.
Tracing is very helpful when debugging multi-agent techniques as a result of it reveals precisely what occurred at every step. You possibly can see whether or not the supervisor adopted the required workflow, which instruments have been referred to as, what proof was gathered, how the decide evaluated the reply, and when the analyst produced the ultimate report.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
def openai_trace_url(trace_id: str) -> str: Â Â Â Â return f“https://platform.openai.com/logs/hint?trace_id={trace_id}” Â Â async def run_research_assistant(question: str) -> MarkdownResearchReport: Â Â Â Â if not OPENAI_API_KEY: Â Â Â Â Â Â Â Â increase RuntimeError( Â Â Â Â Â Â Â Â Â Â Â Â “OPENAI_API_KEY isn’t set. Add it to .env and rerun the setup cell.” Â Â Â Â Â Â Â Â ) Â Â Â Â require_olostep_key() Â Â Â Â Â trace_id = gen_trace_id() Â Â Â Â print(“OpenAI hint ID:”, trace_id) Â Â Â Â print(“OpenAI hint URL:”, openai_trace_url(trace_id)) Â Â Â Â Â current_date = current_date_context() Â Â Â Â current_year = current_year_context() Â Â Â Â immediate = f“”“ Present date: {current_date} Â Present 12 months: {current_year} Â Analysis query: {question} Â Return a refined, reader-friendly Markdown analysis report with substantial element for the person’s particular query. Comply with the required workflow precisely: – Use answer_query first for a easy preliminary reply. – Use the decide agent instantly after the straightforward reply to determine whether or not to cease or proceed. – If the primary decide says the reply isn’t enough, run search_with_scrape. – Use the decide agent instantly after search_with_scrape to determine whether or not to cease or proceed. – If the second decide nonetheless says the proof is weak, don’t decide once more. Run a number of focused search_web calls, select not less than the highest 3 related supply URLs from the search outcomes, and scrape these prime 3 pages for context. – Analyst agent writes the ultimate Markdown report from all reply, decide, search, and scrape proof. Don’t embrace Limitations or Subsequent Steps sections. ““” Â Â Â Â with hint( Â Â Â Â Â Â Â Â workflow_name=“multi_agent_research_assistant_olostep”, Â Â Â Â Â Â Â Â trace_id=trace_id, Â Â Â Â Â Â Â Â metadata={ Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â “pocket book”: “multi_agent_research_assistant_openai_agents_olostep”, Â Â Â Â Â Â Â Â }, Â Â Â Â ): Â Â Â Â Â Â Â Â with custom_span(“supervisor.run”, {“question”: question}): Â Â Â Â Â Â Â Â Â Â Â Â end result = await Runner.run(manager_agent, immediate, max_turns=30) Â Â Â Â Â flush_traces() Â Â Â Â print( Â Â Â Â Â Â Â Â “Hint flushed. Open the URL above to examine supervisor, specialist brokers, instruments, and Olostep spans.” Â Â Â Â ) Â Â Â Â return end result.final_output |
The perform first checks that each API keys can be found. It then creates a hint ID and prints a hint URL so you possibly can examine the total run within the OpenAI hint viewer.
The hint() block teams the total workflow, whereas custom_span() marks the manager-agent run. Because the Olostep instruments additionally use customized spans, you possibly can see each agent choices and API calls in a single place.
Lastly, flush_traces() sends the hint knowledge to OpenAI so the run is out there for assessment.
9. Take a look at the Multi-Agent Analysis Assistant
Now take a look at the total workflow with a pattern analysis query. The assistant will run the supervisor agent, collect proof, decide the standard of that proof, and return a structured Markdown report.
|
example_query = “What is going on on with OpenAI’s Sora shutting down?” Â report = await run_research_assistant(example_query) show(Markdown(report.markdown_report)) |
Whenever you run this cell, the pocket book prints an OpenAI hint ID and hint URL:
|
OpenAI hint ID: trace_45f3333363da420dbcefc8bb8819224c OpenAI hint URL: https://platform.openai.com/logs/hint?trace_id=trace_45f3333363da420dbcefc8bb8819224c |
Click on the hint URL to open the run within the OpenAI hint viewer. This allows you to examine the total execution path throughout the supervisor agent, decide agent, analyst agent, Olostep instruments, and scraping calls.
The hint is helpful as a result of it reveals the precise orchestration course of. You possibly can see when the supervisor agent begins with answer_query, when it sends the end result to the decide agent, and the way the decide decides whether or not the proof is powerful sufficient. If the primary reply isn’t sufficient, the hint additionally reveals when the supervisor makes use of search_with_scrape or focused scraping to assemble higher proof.

After the supervisor completes the analysis course of, the pocket book shows the ultimate Markdown report:

The ultimate report is written in a clear, reader-friendly format with an government abstract, key findings, context, evaluation, supply notes, and references.
In case you face any points working the pocket book or reproducing the outcomes above, you possibly can assessment the total Jupyter Pocket book on GitHub. It consists of the entire setup, helper features, agent definitions, device calls, tracing workflow, and instance output: multi_agent_research_assistant_openai_agents_olostep.ipynb
10. Construct a Internet UI with Reflex
After testing the code within the pocket book, you possibly can flip the analysis assistant right into a easy internet app utilizing Reflex, a Python internet framework for constructing interactive person interfaces.
The online app focuses on making a clear interface the place customers can:
- Enter a analysis query
- Run the multi-agent workflow
- View the agent exercise logs
- Learn the ultimate analysis report
- Obtain the report as a PDF
You will discover the app code within the undertaking repository: Multi-Agent-Analysis-Assistant/app
First, clone the undertaking repository:
|
git clone https://github.com/kingabzpro/Multi-Agent-Analysis-Assistant.git |
Transfer into the undertaking folder and set up the required dependencies:
|
cd Multi–Agent–Analysis–Assistant pip set up –r necessities.txt |
Subsequent, create a .env file from the supplied template and add your API keys:
|
OPENAI_API_KEY=your_openai_api_key OLOSTEP_API_KEY=your_olostep_api_key OPENAI_MODEL=gpt–5.4–mini |
Then run the Reflex app:
As soon as the app begins, open the native URL printed in your terminal. It’s often:
You now have a working internet interface in your multi-agent analysis assistant.
The UI is designed to be easy, quick, and sensible. Whenever you enter a query and click on the search button, the app reveals the workflow logs so you possibly can comply with what the assistant is doing.

The assistant begins by calling the Olostep Reply API to get an preliminary reply. It then sends that proof to the decide agent to verify whether or not the reply is powerful sufficient. If the decide decides extra proof is required, the supervisor agent continues with internet search, scraping, and extra supply gathering earlier than sending every part to the analyst agent for the ultimate report.

The ultimate report is displayed in a clear, skilled format that’s straightforward to learn. You may as well obtain the generated analysis report as a PDF file, making it simpler to avoid wasting, share, or assessment later.

If you do not need to construct the app domestically and solely need to attempt it rapidly, you should use the deployed Hugging Face Area: Multi-Agent Analysis Assistant – a Hugging Face Area by kingabzpro
Closing Ideas
Constructing this multi-agent analysis assistant confirmed how straightforward it’s to create a sensible agentic workflow utilizing specialist brokers and a number of instruments. As an alternative of counting on one giant, costly analysis run each time, the system makes use of a supervisor agent to decide on the best path primarily based on the standard of the proof.
The workflow is designed to steadiness velocity, price, and accuracy. It begins with the Olostep Reply API for a quick first response. If the decide agent provides that reply a robust rating, the analyst agent instantly turns it right into a remaining report. This retains easy analysis duties quick and cost-effective.
If the decide decides the primary reply isn’t robust sufficient, the supervisor agent strikes to Search with Scrape. This offers the system richer proof with out leaping straight right into a deeper and costlier analysis course of. The decide then checks the proof once more. Whether it is ok, the analyst writes the report.
Solely when the proof remains to be weak does the supervisor agent run focused searches and scrape chosen pages. This implies the system can nonetheless produce a extra correct report when the query is complicated, present, or lacking necessary context.
One of the best half is that each question doesn’t price the identical or take the identical period of time. Easy questions can end rapidly, whereas tougher questions get extra analysis depth when wanted. This makes the assistant extra environment friendly, extra dependable, and higher suited to real-world analysis workflows.
On this article, you’ll learn to construct a multi-agent AI analysis assistant utilizing the OpenAI Brokers SDK, the GPT-5.4 mini mannequin, and the Olostep Internet API, together with wire collectively a supervisor agent, specialist sub-agents, and reside internet instruments to provide structured, source-grounded analysis reviews.
Subjects we are going to cowl embrace:
- How one can outline a supervisor agent that orchestrates a decide agent and an analyst agent to progressively collect and consider proof.
- How one can combine Olostep’s Reply, Search, Search-with-Scrape, and Scrape APIs as callable instruments contained in the OpenAI Brokers SDK workflow.
- How one can expose the completed analysis assistant as an interactive internet utility constructed with Reflex, full with PDF export.
How one can Construct a Multi-Agent Analysis Assistant in Python
Introduction
I’ve been experimenting with the OpenAI Brokers SDK, and it has rapidly turn into one in every of my favourite methods to construct agentic AI functions. What stood out to me is how easy it’s to create a multi-agent workflow: you outline a supervisor agent, join it with specialist sub-agents and instruments, and let it determine full the duty.
The supervisor agent can delegate work to different brokers, name instruments immediately, and coordinate the general analysis course of. This makes it potential to construct AI functions that do greater than generate textual content — they will search the net, collect info, arrange findings, and produce grounded outputs.
On this information, we are going to construct a multi-agent AI analysis assistant utilizing the OpenAI Brokers SDK, the GPT-5.4 mini mannequin, and the Olostep Internet API. The assistant will generate a structured analysis report that’s grounded in internet knowledge, straightforward to learn, and produced in just some seconds.
The information additionally consists of the total code, an internet app, and a hyperlink to the deployed model so you possibly can take a look at the system your self. By the top, you’ll perceive how a number of brokers can work collectively to create a sensible analysis assistant from scratch.
1. Set Up the Setting
Earlier than constructing the multi-agent analysis assistant, we have to arrange the Python atmosphere and configure the required API keys.
We’ll use 4 primary packages:
- openai-agents for constructing and working the multi-agent workflow
- olostep for accessing reside internet knowledge
- pydantic for outlining structured outputs
- python-dotenv for loading API keys from a .env file
Run the next command to put in the required packages:
|
pip set up –q –U openai–brokers olostep python–dotenv pydantic |
Subsequent, create a .env file in your undertaking listing. This file will retailer your API keys securely, so you do not want to hardcode them inside your pocket book or utility.
|
OPENAI_API_KEY=your_openai_api_key OLOSTEP_API_KEY=your_olostep_api_key |
You possibly can create your OpenAI API key from the OpenAI Platform. Register to your OpenAI account, go to the API keys part, and generate a brand new key for this undertaking. Be sure your OpenAI API account has billing enabled and not less than $5 in credit out there earlier than working the examples. You might also want to finish account verification to entry the newest fashions.
For Olostep, create a free account from the Olostep web site and generate an API key out of your dashboard. The free plan consists of 500 profitable requests with no bank card required, which is sufficient to take a look at the analysis assistant on this information.
As soon as your keys are prepared, we are going to begin in a Jupyter Pocket book by importing the required libraries and loading the atmosphere variables. This setup prepares the pocket book to work with OpenAI, Olostep, structured outputs, and tracing.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import json import os from datetime import datetime from typing import Any  from dotenv import load_dotenv from IPython.show import Markdown, show from olostep import Olostep from pydantic import BaseModel, Area  from brokers import (     Agent,     Runner,     custom_span,     flush_traces,     function_tool,     gen_trace_id,     hint, )  load_dotenv()  OPENAI_API_KEY = os.getenv(“OPENAI_API_KEY”) OLOSTEP_API_KEY = os.getenv(“OLOSTEP_API_KEY”) |
2. Take a look at Olostep Search with Scraping
Earlier than constructing the total multi-agent workflow, it’s helpful to check whether or not Olostep can search the net and scrape the returned pages efficiently. This step confirms that your API secret is working and that the search outcomes embrace sufficient web page content material for downstream evaluation.
The Olostep Search API is very helpful as a result of it could actually return search outcomes with a built-in scraping choice. As an alternative of solely receiving web page titles, snippets, and hyperlinks, you possibly can ask Olostep to scrape the returned URLs and supply the extracted content material in codecs equivalent to Markdown.
This implies the agent can work with high-quality web page content material immediately, relatively than relying solely on search snippets. It additionally saves time as a result of you do not want to construct a separate search-and-scrape pipeline your self.
|
consumer = Olostep(api_key=OLOSTEP_API_KEY) Â search = consumer.searches.create( Â Â Â Â question=“What are an important latest developments in AI brokers for enterprise analysis?”, Â Â Â Â restrict=5, Â Â Â Â scrape_options={“codecs”: [“markdown”], “timeout”: 25}, ) Â for hyperlink in search.hyperlinks: Â Â Â Â print(hyperlink[“url”], “-“, len(hyperlink.get(“markdown_content”) or “”), “chars”) |
This tells Olostep to scrape every returned web page and supply the extracted content material in Markdown format. Markdown is helpful as a result of it retains the content material readable whereas eradicating pointless web page muddle. The timeout worth provides Olostep sufficient time to fetch and course of every web page.
After the search is full, we loop via the returned hyperlinks and print every URL together with the variety of characters extracted from the web page.
3. Add Helper Capabilities
Earlier than creating the brokers and instruments, we have to add just a few helper features. These utilities preserve the remainder of the code cleaner and make the workflow simpler to debug.
The helper features will deal with six issues:
- Verify whether or not the Olostep API secret is out there
- Create a reusable Olostep consumer
- Convert SDK responses into commonplace Python dictionaries
- Compress giant JSON outputs so they’re simpler to examine
- Add the present date and 12 months as context for the brokers
- Normalize search outcomes into an easier format for the brokers
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
class OlostepError(RuntimeError):     “”“Raised when an Olostep SDK request fails.”“”  def require_olostep_key() -> str:     if not OLOSTEP_API_KEY:         increase OlostepError(             “OLOSTEP_API_KEY isn’t set. Add it to .env and rerun the setup cell.”         )     return OLOSTEP_API_KEY  def get_olostep_client() -> Olostep:     return Olostep(api_key=require_olostep_key())  def sdk_result_to_dict(end result: Any) -> dict[str, Any]:     if hasattr(end result, “model_dump”):         return end result.model_dump()     if hasattr(end result, “__dict__”):         return {             key: worth for key, worth in vars(end result).gadgets() if not key.startswith(“_”)         }     return {“worth”: str(end result)}  def compact_json(knowledge: Any, max_chars: int = 8000) -> str:     textual content = json.dumps(knowledge, ensure_ascii=False, indent=2, default=str)     if len(textual content) <= max_chars:         return textual content     return textual content[:max_chars] + “n… [truncated]”  def current_date_context() -> str:     return datetime.now().strftime(“%B %d, %Y”)  def current_year_context() -> str:     return str(datetime.now().12 months)  def normalize_search_links(     hyperlinks: listing[dict[str, Any]], restrict: int = 8 ) -> listing[dict[str, Any]]:     rows = []     for hyperlink in hyperlinks[:limit]:         markdown = hyperlink.get(“markdown_content”) or “”         rows.append(             {                 “title”: hyperlink.get(“title”) or “Untitled”,                 “url”: hyperlink.get(“url”) or “”,                 “description”: hyperlink.get(“description”) or “”,                 “markdown_chars”: len(markdown),                 “markdown_preview”: markdown[:1500] if markdown else “”,             }         )     return rows |
4. Outline Structured Output Fashions
Subsequent, outline the structured outputs that the brokers will return. These fashions make the workflow extra dependable as a result of every agent should return info in a constant format.
The decide agent makes use of the Judgment mannequin to determine whether or not the gathered proof is powerful sufficient. The analyst agent makes use of the MarkdownResearchReport mannequin to return the ultimate report as polished Markdown.
|
class Judgment(BaseModel): Â Â Â Â is_good_enough: bool = Area( Â Â Â Â Â Â Â Â description=“Whether or not the reply is enough for the person question, which means rating >= 0.85.” Â Â Â Â ) Â Â Â Â rating: float = Area(ge=0, le=1, description=“High quality rating from 0 to 1.”) Â Â Â Â cause: str = Area(description=“Quick clarification of the choice.”) Â Â Â Â missing_information: listing[str] = Area( Â Â Â Â Â Â Â Â default_factory=listing, description=“Vital gaps to repair.” Â Â Â Â ) Â class MarkdownResearchReport(BaseModel): Â Â Â Â markdown_report: str = Area( Â Â Â Â Â Â Â Â description=“Full Markdown report with polished headings, clear evaluation, reader-friendly construction, and citations.” Â Â Â Â ) |
Judgment works because the quality-control schema. It helps the decide agent determine whether or not the gathered proof is powerful sufficient or whether or not the supervisor agent ought to proceed looking.
MarkdownResearchReport defines the ultimate analysis output. Because the remaining app solely wants the finished report, this mannequin retains a single markdown_report subject as an alternative of additional metadata fields. This makes the output easier and simpler to show within the pocket book, internet app, and PDF export.
5. Create Olostep Device Capabilities
Now create the instruments that the supervisor agent can name in the course of the analysis course of. These instruments wrap Olostep’s Reply API, Search API, Search with Scrape, and Scrape API.
Every device consists of tracing spans so you possibly can examine what occurred throughout execution within the OpenAI hint viewer. That is helpful for debugging as a result of you possibly can see which device was referred to as, what enter it obtained, and the way the supervisor agent moved via the workflow.
Reply Question Device
This device asks Olostep for a fast reply to the person’s analysis query. It’s used as step one within the workflow earlier than deciding whether or not extra analysis is required.
|
@function_tool async def answer_query(question: str) -> str: Â Â Â Â “”“Reply a natural-language analysis question utilizing Olostep Reply API.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span(“olostep.answer_query”, {“question”: question}): Â Â Â Â Â Â Â Â Â Â Â Â end result = get_olostep_client().solutions.create(activity=question) Â Â Â Â Â Â Â Â Â Â Â Â return compact_json(sdk_result_to_dict(end result)) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Reply API failed: {exc}”) from exc |
Search Internet Device
This device runs an ordinary internet search and returns normalized outcomes. It’s helpful when the assistant wants to find further sources earlier than scraping particular pages.
The output is deliberately compact. As an alternative of returning the total uncooked API response, the device returns the question and a cleaned listing of search outcomes. This makes the response simpler for the supervisor agent to learn and reduces pointless context.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@function_tool async def search_web(question: str, restrict: int = 8) -> str: Â Â Â Â “”“Search the net utilizing Olostep Search and return normalized outcomes.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span(“olostep.search_web”, {“question”: question, “restrict”: restrict}): Â Â Â Â Â Â Â Â Â Â Â Â search = get_olostep_client().searches.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â question=question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge = sdk_result_to_dict(search) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “outcomes”: normalize_search_links( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge.get(“hyperlinks”, []), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Search API failed: {exc}”) from exc |
Search with Scrape Device
This device searches the net and scrapes the returned pages in a single step. It provides the analysis assistant richer proof than search snippets alone.
This is likely one of the most necessary instruments within the undertaking as a result of it lets the agent retrieve each hyperlinks and web page content material from a single name. As an alternative of first looking the net, choosing URLs, after which scraping every one individually, the device can return usable Markdown content material immediately from the found pages.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
@function_tool async def search_with_scrape(question: str, restrict: int = 5) -> str: Â Â Â Â “”“Search the net and scrape every returned hyperlink utilizing Olostep Search with Scrape.”“” Â Â Â Â scrape_options = { Â Â Â Â Â Â Â Â “codecs”: [“markdown”], Â Â Â Â Â Â Â Â “timeout”: 25, Â Â Â Â } Â Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span( Â Â Â Â Â Â Â Â Â Â Â Â “olostep.search_with_scrape”, Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “restrict”: restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “scrape_options”: scrape_options, Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â ): Â Â Â Â Â Â Â Â Â Â Â Â search = get_olostep_client().searches.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â question=question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scrape_options=scrape_options, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge = sdk_result_to_dict(search) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “outcomes”: normalize_search_links( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â knowledge.get(“hyperlinks”, []), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â restrict=restrict, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â max_chars=12000, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Search with Scrape failed: {exc}”) from exc |
Scrape URL Device
This device scrapes a single URL and returns compact web page content material. The supervisor agent makes use of it when it wants deeper proof from chosen sources.
For instance, the supervisor could first use search_web to search out related pages, then use scrape_url to retrieve the total content material from essentially the most helpful hyperlinks.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@function_tool async def scrape_url(url: str) -> str: Â Â Â Â “”“Scrape one URL with Olostep and return compact web page content material.”“” Â Â Â Â attempt: Â Â Â Â Â Â Â Â with custom_span( Â Â Â Â Â Â Â Â Â Â Â Â “olostep.scrape_url”, Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “url”: url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “codecs”: [“markdown”], Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â ): Â Â Â Â Â Â Â Â Â Â Â Â scrape = get_olostep_client().scrapes.create( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â url=url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â codecs=[“markdown”], Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â Â Â Â Â Â Â Â Â return compact_json( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “url”: url, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â “scrape”: sdk_result_to_dict(scrape), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â max_chars=10000, Â Â Â Â Â Â Â Â Â Â Â Â ) Â Â Â Â Â besides Exception as exc: Â Â Â Â Â Â Â Â increase OlostepError(f“Olostep Scrape API failed: {exc}”) from exc |
These instruments give the supervisor agent other ways to assemble proof. It might probably begin with a fast reply, seek for extra sources, use Search with Scrape for richer context, or scrape a particular URL when it wants extra element.
6. Construct the Specialist Brokers
The workflow makes use of two specialist brokers: a decide agent and an analyst agent.
The decide agent checks whether or not the gathered proof is powerful sufficient to reply the person’s query. The analyst agent then turns the accredited proof into a refined Markdown analysis report.
First, outline the mannequin that each specialist brokers will use:
Decide Agent
The decide agent evaluates reply high quality. It checks whether or not the reply is restricted, present, source-backed, and full sufficient to cease the analysis course of.
That is necessary as a result of the supervisor agent shouldn’t produce a remaining report from weak proof. If the reply is imprecise, outdated, unsupported, or lacking key particulars, the decide agent will reject it and the supervisor agent can proceed looking.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
judge_agent = Agent( Â Â Â Â identify=“Decide agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â “You decide whether or not the supplied reply is nice sufficient for the unique analysis query. “ Â Â Â Â Â Â Â Â “Reward direct, particular, source-backed solutions. Reject imprecise, stale, or unsupported solutions. “ Â Â Â Â Â Â Â Â “Be strict: is_good_enough have to be true solely when rating >= 0.85 and the proof immediately solutions “ Â Â Â Â Â Â Â Â “the query with concrete supply content material, topic-specific element, and applicable recency. “ Â Â Â Â Â Â Â Â “For present occasions, product standing, insurance policies, pricing, or factual claims that will change, require latest “ Â Â Â Â Â Â Â Â “major or extremely respected sources. Don’t mark proof enough if any vital hole stays. “ Â Â Â Â Â Â Â Â “Calibrate scores this fashion: 0.85-1.0 means enough to cease with robust supply help and no vital gaps; “ Â Â Â Â Â Â Â Â “0.75-0.84 means robust however nonetheless lacking one necessary supply, element, recency verify, or protection space; “ Â Â Â Â Â Â Â Â “0.50-0.74 means related partial proof that wants extra analysis; 0.25-0.49 means skinny, imprecise, stale, “ Â Â Â Â Â Â Â Â “or weakly associated proof; beneath 0.25 is just for empty, unusable, or principally unrelated proof. “ Â Â Â Â Â Â Â Â “Don’t mark proof enough simply because it’s believable or directionally appropriate. “ Â Â Â Â Â Â Â Â “Return solely the structured judgment.” Â Â Â Â ), Â Â Â Â output_type=Judgment, ) |
The decide agent returns a Judgment object. This consists of whether or not the proof is nice sufficient, a top quality rating, a brief cause, and any lacking info that also must be addressed.
Analyst Agent
The analyst agent writes the ultimate Markdown report. It turns the gathered proof right into a readable analysis transient with clear sections, supply notes, and references.
This agent is accountable for making the output helpful for knowledgeable reader. As an alternative of merely summarizing uncooked device outputs, it organizes the findings into a whole report that explains the subject, highlights an important proof, and cites the sources used.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
analyst_agent = Agent( Â Â Â Â identify=“Analyst agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â “You write a correct Markdown analysis report from the proof. “ Â Â Â Â Â Â Â Â “Write for knowledgeable reader who needs a transparent, polished analysis transient on any subject. “ Â Â Â Â Â Â Â Â “Adapt the report back to the person’s query. The markdown_report have to be substantial, straightforward to scan, and use these basic sections solely: “ Â Â Â Â Â Â Â Â “Government Abstract, Key Findings, Context, Proof Overview, Detailed Evaluation, Implications, Supply Notes, and References. “ Â Â Â Â Â Â Â Â “If the subject is event-driven, embrace timeline particulars inside Context or Detailed Evaluation as an alternative of including a separate Timeline part. “ Â Â Â Â Â Â Â Â “If the subject is comparative, embrace a compact comparability desk inside Detailed Evaluation. “ Â Â Â Â Â Â Â Â “Don’t embrace sections titled Limitations, Subsequent Steps, Suggestions, or Motion Objects. “ Â Â Â Â Â Â Â Â “Keep away from naked caveats like ‘I relied on…’. As an alternative, combine supply high quality naturally in Supply Notes. “ Â Â Â Â Â Â Â Â “Use quick paragraphs, bullets the place useful, and citations as Markdown hyperlinks or URL bullets. “ Â Â Â Â Â Â Â Â “Add sufficient context {that a} non-expert reader understands the difficulty, why it issues, and what proof helps it. “ Â Â Â Â Â Â Â Â “Don’t use emoji, return-arrow symbols, backlink icons, or ornamental icons wherever within the report. “ Â Â Â Â Â Â Â Â “In References, listing solely plain Markdown bullets or numbered gadgets with the supply identify and URL. “ Â Â Â Â Â Â Â Â “Return solely the structured report.” Â Â Â Â ), Â Â Â Â output_type=MarkdownResearchReport, ) |
The analyst agent returns a MarkdownResearchReport object with one subject: markdown_report. This retains the ultimate output easy as a result of the entire title, abstract, findings, evaluation, supply notes, and references are all included contained in the Markdown report itself.
7. Create the Supervisor Agent
The supervisor agent is the orchestrator. It controls the total analysis workflow and decides which device or specialist agent ought to run subsequent.
The workflow follows this sample:
- Begin with a fast reply utilizing the Olostep Reply API
- Ask the decide agent whether or not the reply is nice sufficient
- If not, run Search with Scrape for stronger proof
- Ask the decide agent once more
- If the proof remains to be weak, run focused searches and scrape essentially the most related pages
- Ask the analyst agent to jot down the ultimate report
First, convert the decide and analyst brokers into instruments. This enables the supervisor agent to name them in the course of the workflow.
|
judge_tool = judge_agent.as_tool( Â Â Â Â tool_name=“judge_answer_quality”, Â Â Â Â tool_description=“Decide whether or not a solution or proof is nice sufficient for the unique analysis query.”, ) Â analyst_tool = analyst_agent.as_tool( Â Â Â Â tool_name=“write_markdown_research_report”, Â Â Â Â tool_description=“Write the ultimate structured Markdown analysis report from the gathered proof.”, ) |
Now outline the supervisor agent. This agent doesn’t reply from reminiscence. As an alternative, it follows a transparent analysis course of: reply, decide, search, decide once more, scrape if wanted, after which write the ultimate report.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
manager_agent = Agent( Â Â Â Â identify=“Supervisor analysis agent”, Â Â Â Â mannequin=MODEL, Â Â Â Â directions=( Â Â Â Â Â Â Â Â f“Present date: {current_date_context()}n” Â Â Â Â Â Â Â Â f“Present 12 months: {current_year_context()}nn” Â Â Â Â Â Â Â Â “You’re the orchestrator for a multi-agent analysis assistant. You could handle the workflow, “ Â Â Â Â Â Â Â Â “not reply from your individual reminiscence. Comply with this coverage precisely:n” Â Â Â Â Â Â Â Â “1. All the time name answer_query first to get a easy preliminary reply for the person’s query.n” Â Â Â Â Â Â Â Â “2. Instantly name judge_answer_quality on the unique query plus the answer_query end result. “ Â Â Â Â Â Â Â Â “If the decide returns is_good_enough=true and rating >= 0.85, cease researching and name “ Â Â Â Â Â Â Â Â “write_markdown_research_report with the query, reply end result, and judgment.n” Â Â Â Â Â Â Â Â “3. If the primary judgment is weak, name search_with_scrape for the unique query. “ Â Â Â Â Â Â Â Â “Instantly name judge_answer_quality once more on the unique query plus the answer_query end result, “ Â Â Â Â Â Â Â Â “first judgment, and search_with_scrape end result. If this second decide returns is_good_enough=true “ Â Â Â Â Â Â Â Â “and rating >= 0.85, cease researching and name write_markdown_research_report with all proof.n” Â Â Â Â Â Â Â Â “4. If the second judgment remains to be weak, don’t name the decide once more. Run a number of focused “ Â Â Â Â Â Â Â Â “search_web calls first, utilizing the decide’s missing_information to kind the searches. Examine the “ Â Â Â Â Â Â Â Â “search outcomes, select not less than the highest 3 related supply URLs most definitely to reply the lacking “ Â Â Â Â Â Â Â Â “factors, then name scrape_url on every of these prime 3 pages. Scrape greater than 3 provided that clearly wanted.n” Â Â Â Â Â Â Â Â “5. Name write_markdown_research_report precisely as soon as on the finish, utilizing each reply, judgment, “ Â Â Â Â Â Â Â Â “search end result, and scraped web page. The analyst should produce the ultimate MarkdownResearchReport.n” Â Â Â Â Â Â Â Â “6. Return solely the ultimate MarkdownResearchReport. Don’t return an off-the-cuff chat reply, device transcript, or plan.” Â Â Â Â ), Â Â Â Â instruments=[ Â Â Â Â Â Â Â Â answer_query, Â Â Â Â Â Â Â Â judge_tool, Â Â Â Â Â Â Â Â search_with_scrape, Â Â Â Â Â Â Â Â search_web, Â Â Â Â Â Â Â Â scrape_url, Â Â Â Â Â Â Â Â analyst_tool, Â Â Â Â ], Â Â Â Â output_type=MarkdownResearchReport, ) |
The supervisor agent is the core of the system. It decides when the primary reply is sufficient, when extra proof is required, and when to name the analyst agent to provide the ultimate report.
The important thing concept is that the supervisor doesn’t depend on a single device name. It begins with a quick reply, checks high quality, and solely does deeper analysis when wanted. This retains the workflow environment friendly whereas nonetheless permitting the assistant to assemble stronger proof for extra complicated questions.
8. Run the Analysis Assistant with Tracing
The ultimate perform runs the supervisor agent and returns a structured analysis report. It additionally creates an OpenAI hint ID so you possibly can examine the total workflow, together with supervisor choices, specialist agent calls, device utilization, and Olostep spans.
Tracing is very helpful when debugging multi-agent techniques as a result of it reveals precisely what occurred at every step. You possibly can see whether or not the supervisor adopted the required workflow, which instruments have been referred to as, what proof was gathered, how the decide evaluated the reply, and when the analyst produced the ultimate report.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
def openai_trace_url(trace_id: str) -> str: Â Â Â Â return f“https://platform.openai.com/logs/hint?trace_id={trace_id}” Â Â async def run_research_assistant(question: str) -> MarkdownResearchReport: Â Â Â Â if not OPENAI_API_KEY: Â Â Â Â Â Â Â Â increase RuntimeError( Â Â Â Â Â Â Â Â Â Â Â Â “OPENAI_API_KEY isn’t set. Add it to .env and rerun the setup cell.” Â Â Â Â Â Â Â Â ) Â Â Â Â require_olostep_key() Â Â Â Â Â trace_id = gen_trace_id() Â Â Â Â print(“OpenAI hint ID:”, trace_id) Â Â Â Â print(“OpenAI hint URL:”, openai_trace_url(trace_id)) Â Â Â Â Â current_date = current_date_context() Â Â Â Â current_year = current_year_context() Â Â Â Â immediate = f“”“ Present date: {current_date} Â Present 12 months: {current_year} Â Analysis query: {question} Â Return a refined, reader-friendly Markdown analysis report with substantial element for the person’s particular query. Comply with the required workflow precisely: – Use answer_query first for a easy preliminary reply. – Use the decide agent instantly after the straightforward reply to determine whether or not to cease or proceed. – If the primary decide says the reply isn’t enough, run search_with_scrape. – Use the decide agent instantly after search_with_scrape to determine whether or not to cease or proceed. – If the second decide nonetheless says the proof is weak, don’t decide once more. Run a number of focused search_web calls, select not less than the highest 3 related supply URLs from the search outcomes, and scrape these prime 3 pages for context. – Analyst agent writes the ultimate Markdown report from all reply, decide, search, and scrape proof. Don’t embrace Limitations or Subsequent Steps sections. ““” Â Â Â Â with hint( Â Â Â Â Â Â Â Â workflow_name=“multi_agent_research_assistant_olostep”, Â Â Â Â Â Â Â Â trace_id=trace_id, Â Â Â Â Â Â Â Â metadata={ Â Â Â Â Â Â Â Â Â Â Â Â “question”: question, Â Â Â Â Â Â Â Â Â Â Â Â “pocket book”: “multi_agent_research_assistant_openai_agents_olostep”, Â Â Â Â Â Â Â Â }, Â Â Â Â ): Â Â Â Â Â Â Â Â with custom_span(“supervisor.run”, {“question”: question}): Â Â Â Â Â Â Â Â Â Â Â Â end result = await Runner.run(manager_agent, immediate, max_turns=30) Â Â Â Â Â flush_traces() Â Â Â Â print( Â Â Â Â Â Â Â Â “Hint flushed. Open the URL above to examine supervisor, specialist brokers, instruments, and Olostep spans.” Â Â Â Â ) Â Â Â Â return end result.final_output |
The perform first checks that each API keys can be found. It then creates a hint ID and prints a hint URL so you possibly can examine the total run within the OpenAI hint viewer.
The hint() block teams the total workflow, whereas custom_span() marks the manager-agent run. Because the Olostep instruments additionally use customized spans, you possibly can see each agent choices and API calls in a single place.
Lastly, flush_traces() sends the hint knowledge to OpenAI so the run is out there for assessment.
9. Take a look at the Multi-Agent Analysis Assistant
Now take a look at the total workflow with a pattern analysis query. The assistant will run the supervisor agent, collect proof, decide the standard of that proof, and return a structured Markdown report.
|
example_query = “What is going on on with OpenAI’s Sora shutting down?” Â report = await run_research_assistant(example_query) show(Markdown(report.markdown_report)) |
Whenever you run this cell, the pocket book prints an OpenAI hint ID and hint URL:
|
OpenAI hint ID: trace_45f3333363da420dbcefc8bb8819224c OpenAI hint URL: https://platform.openai.com/logs/hint?trace_id=trace_45f3333363da420dbcefc8bb8819224c |
Click on the hint URL to open the run within the OpenAI hint viewer. This allows you to examine the total execution path throughout the supervisor agent, decide agent, analyst agent, Olostep instruments, and scraping calls.
The hint is helpful as a result of it reveals the precise orchestration course of. You possibly can see when the supervisor agent begins with answer_query, when it sends the end result to the decide agent, and the way the decide decides whether or not the proof is powerful sufficient. If the primary reply isn’t sufficient, the hint additionally reveals when the supervisor makes use of search_with_scrape or focused scraping to assemble higher proof.

After the supervisor completes the analysis course of, the pocket book shows the ultimate Markdown report:

The ultimate report is written in a clear, reader-friendly format with an government abstract, key findings, context, evaluation, supply notes, and references.
In case you face any points working the pocket book or reproducing the outcomes above, you possibly can assessment the total Jupyter Pocket book on GitHub. It consists of the entire setup, helper features, agent definitions, device calls, tracing workflow, and instance output: multi_agent_research_assistant_openai_agents_olostep.ipynb
10. Construct a Internet UI with Reflex
After testing the code within the pocket book, you possibly can flip the analysis assistant right into a easy internet app utilizing Reflex, a Python internet framework for constructing interactive person interfaces.
The online app focuses on making a clear interface the place customers can:
- Enter a analysis query
- Run the multi-agent workflow
- View the agent exercise logs
- Learn the ultimate analysis report
- Obtain the report as a PDF
You will discover the app code within the undertaking repository: Multi-Agent-Analysis-Assistant/app
First, clone the undertaking repository:
|
git clone https://github.com/kingabzpro/Multi-Agent-Analysis-Assistant.git |
Transfer into the undertaking folder and set up the required dependencies:
|
cd Multi–Agent–Analysis–Assistant pip set up –r necessities.txt |
Subsequent, create a .env file from the supplied template and add your API keys:
|
OPENAI_API_KEY=your_openai_api_key OLOSTEP_API_KEY=your_olostep_api_key OPENAI_MODEL=gpt–5.4–mini |
Then run the Reflex app:
As soon as the app begins, open the native URL printed in your terminal. It’s often:
You now have a working internet interface in your multi-agent analysis assistant.
The UI is designed to be easy, quick, and sensible. Whenever you enter a query and click on the search button, the app reveals the workflow logs so you possibly can comply with what the assistant is doing.

The assistant begins by calling the Olostep Reply API to get an preliminary reply. It then sends that proof to the decide agent to verify whether or not the reply is powerful sufficient. If the decide decides extra proof is required, the supervisor agent continues with internet search, scraping, and extra supply gathering earlier than sending every part to the analyst agent for the ultimate report.

The ultimate report is displayed in a clear, skilled format that’s straightforward to learn. You may as well obtain the generated analysis report as a PDF file, making it simpler to avoid wasting, share, or assessment later.

If you do not need to construct the app domestically and solely need to attempt it rapidly, you should use the deployed Hugging Face Area: Multi-Agent Analysis Assistant – a Hugging Face Area by kingabzpro
Closing Ideas
Constructing this multi-agent analysis assistant confirmed how straightforward it’s to create a sensible agentic workflow utilizing specialist brokers and a number of instruments. As an alternative of counting on one giant, costly analysis run each time, the system makes use of a supervisor agent to decide on the best path primarily based on the standard of the proof.
The workflow is designed to steadiness velocity, price, and accuracy. It begins with the Olostep Reply API for a quick first response. If the decide agent provides that reply a robust rating, the analyst agent instantly turns it right into a remaining report. This retains easy analysis duties quick and cost-effective.
If the decide decides the primary reply isn’t robust sufficient, the supervisor agent strikes to Search with Scrape. This offers the system richer proof with out leaping straight right into a deeper and costlier analysis course of. The decide then checks the proof once more. Whether it is ok, the analyst writes the report.
Solely when the proof remains to be weak does the supervisor agent run focused searches and scrape chosen pages. This implies the system can nonetheless produce a extra correct report when the query is complicated, present, or lacking necessary context.
One of the best half is that each question doesn’t price the identical or take the identical period of time. Easy questions can end rapidly, whereas tougher questions get extra analysis depth when wanted. This makes the assistant extra environment friendly, extra dependable, and higher suited to real-world analysis workflows.















