# Concurrent Research Agent

In this guide we will create a **Research Agent** that takes a given user question and automatically does several things:

* Breaks the question into discrete research tasks
* Launches multiple sub‑agents that search the web in parallel
* Collects and deduplicates their findings
* Produces a concise, well‑structured final answer

We leverage the built‑in concurrency primitives such as **`Std.Spawn Processes from List`** and **`Std.MergeAll`**.

{% embed url="<https://youtu.be/_KOrmVXIfpc@>" %}

***

## High‑Level Architecture

Our solution is split into three main phases:

| Phase                          | Responsibility                                                                                                                                                             |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **1) Task Planning**           | Turn the user prompt into a list of concrete research tasks                                                                                                                |
| **2) Concurrent Research**     | <p>Spawn one child process per task, each of which:<br>• Transforms its task into a search engine query<br>• Queries the Tavily Search API<br>• Summarizes the results</p> |
| **3) Aggregation & Synthesis** | Merge all child outputs, filter failures, and craft the master answer                                                                                                      |

<figure><picture><source srcset="/files/HFNgP5kHnd6xm1tShJkC" media="(prefers-color-scheme: dark)"><img src="/files/wuEETR4kX2UV7itdrY5t" alt=""></picture><figcaption></figcaption></figure>

## Phase 1: Task Planning

The master agent needs a **machine‑readable** list of subtasks. Midio’s `Chat Complete` (avilable in the open-ai [package](/midio-docs/package-manager.md)) node supports [**structured output**](/midio-docs/guides/building-agents.md#structured-output) which lets an LLM return valid JSON that is guaranteed to match a user‑defined schema.

1. We can force the LLM to output a custom schema by providing an object like the following to the `response format` input. We also need to mention in the system prompt that we expect JSON output.

   ```json
   {
       name: "AgentDeployments",
       description: "A list of agents to deploy, which agents and what their task is.",
       schema: {
           agents: [
               {
                   name: "WebResearchAgent",
                   task: "A description of what the agent should research."
               }
           ]
       }
   }
   ```
2. To the `system message` input, we pass the following

   ```
   You are a senior researcher.
   Break the following question into distinct, non‑overlapping web research tasks.
   Spawn at least 3 tasks, at most 6.
   Return an array of objects that conforms to the provided JSON Schema.
   ```
3. And the users query is passed directly to the `user message` input.

<figure><picture><source srcset="/files/bHi8bMb11SVA3lCQy5NJ" media="(prefers-color-scheme: dark)"><img src="/files/w3AHvJUdbT1M4IEhW2w8" alt=""></picture><figcaption></figcaption></figure>

## Phase 2: Concurrent Research

### 1. Spawning Child Processes

We can spawn a process for each generated task by using the [**`Std.Spawn Processes from List`**](/midio-docs/built-in-nodes/core-std.md#spawn-processes-from-list) node, and connect the agents field from the response of the `Generate Research Tasks` function.

We can then connect the `child spawned` trigger (which is triggered once per item) to the `Search Web and Summarize` function.

### Inside the Research Sub‑Agent

The sub‑agent receives a single task object. It first searches the web, and then summarizes its findings. Here is an example of a task object. Generated by the previous step.

```json
{ "task": "Compare the energy density of li‑ion vs. sodium‑ion batteries" }
```

### 2. Craft a Search Query

A `Chat Complete` call turns the (sometimes verbose) task into a concise search‑engine query using the following prompt:

{% code overflow="wrap" %}

```
You are given a task, and you should convert it into a search query that you might put into a google search, and expect resources that provide information to answer the task.
```

{% endcode %}

The response is then piped directly into the query input of a [`Tavily.Search`](http://tavily.search) node. You can add the Tavily package using the package manager in the editor.

<figure><picture><source srcset="/files/yWhFSuMOBYd1Wyfwtffn" media="(prefers-color-scheme: dark)"><img src="/files/gFRC3byRtsb3n3BjScDY" alt=""></picture><figcaption></figcaption></figure>

### 3. Convert Pages to Markdown

For each search result we get back from Tavily, we convert it to Markdown using the `Html to Markdown` function in the **web-tools** [package](/midio-docs/package-manager.md). We use `Spawn Processes from List` here as well to do this task concurrently.

{% hint style="info" %}
Tavily supports returning a summary of the page results automatically, but we do it manually here for demo purposes.
{% endhint %}

<figure><picture><source srcset="/files/4S4cFhWRBc7aNEw9eZEK" media="(prefers-color-scheme: dark)"><img src="/files/5hIYSLSnOZ2kcU5Et84H" alt=""></picture><figcaption></figcaption></figure>

### 4. Summarize Findings

Another `Chat Complete` node receives both the **task** and **raw search results**, and is prompted to combine them into a task summary.

{% code overflow="wrap" %}

```
You are a web research summarizer agent.

The user will provide you the result of a web search, as well a description of a research task that you are tasked with addressing.

Use the web search results and task description to create a summary. Expect the output of your summary to be used by another agent which will combine it with other search results performed by other agents similar to you.
```

{% endcode %}

## Phase 3: Aggregation & Synthesis

The final step is to combine all the research data and produce a single response. We do this with another LLM call, with the following prompt:

{% code overflow="wrap" %}

```
You are a web research summarizer agent.

The user will provide you the result of a web search, as well a description of a research task that you are tasked with addressing.

Use the web search results and task description to create a summary. Expect the output
of your summary to be used by another agent which will combine it with other search results performed by other agents similar to you.
```

{% endcode %}

For its user message we pass the search results and the original user query using the following expression string template:

```
"<data>
  ${data}
</data>
<user_query>
  ${userQuery}
</user_query>"
```

<figure><picture><source srcset="/files/L73VfO7y4NqUiAhwP8OU" media="(prefers-color-scheme: dark)"><img src="/files/xeaEAKx5iwcEb5lJ0I1r" alt=""></picture><figcaption></figcaption></figure>

{% hint style="info" %}
We also make sure to remove any null values from the inputs list, which might appear if a research agent fails for some reason.
{% endhint %}

### Exposing the Agent as a REST API

To make the agent callable from any frontend (e.g. Lovable, curl, or your own app), we can hook it up to an `Endpoint` event node like this:

<figure><picture><source srcset="/files/RimQeDTYFoNFYKwhbBxX" media="(prefers-color-scheme: dark)"><img src="/files/wJmTuIoogbHUqa6WhoF6" alt=""></picture><figcaption></figcaption></figure>

And return a response like this:

<figure><picture><source srcset="/files/qyRT5GHtD2kNiTSh2Z7L" media="(prefers-color-scheme: dark)"><img src="/files/KXxN6PHFJ1Zz5CDZnZtz" alt=""></picture><figcaption></figcaption></figure>

Your research micro service is now live at: [`https://<your-project-name>.midio.dev:3001/research`](https://github.com/midio-code/midio-docs/blob/master/tutorials/https:/%3Cyour-project-name%3E.midio.dev:3001/research?query/README.md) and expecting a single query parameter named `query`. You can call it like this using curl, for example:

{% code overflow="wrap" %}

```
curl https://<your-project-name>.midio.dev:3001/research?query=what+is+going+on+in+tech
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.midio.com/midio-docs/tutorials/concurrent-research-agent.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
