# Creating Multi-Agent Research Crews with Specialized Roles: CrewAI and Agno Patterns Explained

> Build powerful multi-agent research crews with CrewAI and Agno. Leverage specialized agents for search, analysis, and writing to generate comprehensive, hallucination-resistant reports.

- Repository: [Arindam Majumder /awesome-ai-apps](https://github.com/Arindam200/awesome-ai-apps)
- Tags: tutorial
- Published: 2026-05-06

---

**Multi-agent research crews combine purpose-specific agents—such as searchers, analysts, and writers—into sequential workflows using frameworks like CrewAI or Agno, where each role processes the output of the previous stage to produce comprehensive, hallucination-resistant reports.**

The `Arindam200/awesome-ai-apps` repository provides production-ready implementations for creating multi-agent research crews with specialized roles. By analyzing the CrewAI starter and the Agno-based Deep Researcher Agent, you can architect AI teams where distinct agents handle search, synthesis, and writing tasks in a coordinated pipeline.

## Architectural Blueprint for Research Crews

Both implementations in the repository follow a consistent four-layer architecture that separates concerns between agent definition, task orchestration, and execution flow.

### Agent Layer

Each specialized role is encapsulated as a distinct `Agent` instance with its own description, instructions, and model configuration. In [`advance_ai_agents/deep_researcher_agent/agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/advance_ai_agents/deep_researcher_agent/agents.py), the three agents—`searcher`, `analyst`, and `writer`—bind to the same Nebius model (`deepseek-ai/DeepSeek-V3-0324`) but operate with different system prompts that shape their specific behaviors and constraints.

### Task and Workflow Orchestration

CrewAI utilizes `Task` and `Crew` abstractions defined in [`starter_ai_agents/crewai_starter/main.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/starter_ai_agents/crewai_starter/main.py), setting `process=Process.sequential` to enforce strict execution order. Agno implements a `Workflow` subclass (`DeepResearcherAgent`) that manually sequences agent execution within its `run()` method, capturing intermediate outputs and streaming the final report with fine-grained control over error handling and logging.

### Tooling and Infrastructure

The Deep Researcher integrates **ScrapeGraph** via `ScrapeGraphTools` (line 25 of [`agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/agents.py)) to fetch live web data during the search phase. Both projects include `.env.example` files for API key management (Nebius and Scrapegraph), while the Deep Researcher additionally provides an MCP server configuration in [`server.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/server.py) for external tool invocation.

## Building a Single-Agent Crew with CrewAI

The minimal implementation in [`starter_ai_agents/crewai_starter/main.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/starter_ai_agents/crewai_starter/main.py) demonstrates the fundamental pattern: create an agent, define a task, and launch a crew.

```bash
cd starter_ai_agents/crewai_starter
pip install -r requirements.txt   # or `uv sync`

cp .env.example .env               # add your Nebius API key

python main.py

```

The script instantiates a `researcher` agent, wraps it in a `Task` object, and launches a `Crew` that prints generated paragraphs directly to the console.

## Extending to Multi-Agent Workflows

### Adding an Analyst Role to CrewAI

To expand beyond a single researcher, instantiate additional `Agent` objects and append their corresponding `Task` definitions to the crew's task list. The following extension to [`crewai_starter/main.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/crewai_starter/main.py) adds a synthesis step:

```python

# Add after the researcher definition in crewai_starter/main.py

analyst = Agent(
    role='Senior Analyst',
    goal='Synthesize research findings',
    verbose=True,
    llm=LLM(model="nebius/Qwen/Qwen3-235B-A22B", api_key=os.getenv("NEBIUS_API_KEY")),
    backstory='You have a knack for turning raw data into actionable insights.'
)

analysis_task = Task(
    description='Summarize the research paragraphs and highlight key trends',
    expected_output='A concise bullet-point summary',
    agent=analyst,
)

tech_crew = Crew(
    agents=[researcher, analyst],
    tasks=[research_task, analysis_task],
    process=Process.sequential,
)

```

Now the crew runs two tasks in strict sequence: research followed by analysis, with the `Crew` internals passing results implicitly between stages.

### Three-Stage Pipeline with Agno

The `DeepResearcherAgent` class in [`advance_ai_agents/deep_researcher_agent/agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/advance_ai_agents/deep_researcher_agent/agents.py) implements a sophisticated search→analysis→writing pipeline. The `run()` method explicitly chains agent outputs to prevent hallucination, extracting only the links and content that the previous stage supplied (see detailed instruction blocks in lines 64-71).

To execute the Deep Researcher:

```bash
cd advance_ai_agents/deep_researcher_agent
uv sync                       # install deps

cp .env.example .env          # fill NEBIUS_API_KEY & SGAI_API_KEY

uv run python agents.py       # prints the full report

# Or launch the UI:

uv run streamlit run app.py

```

The orchestration logic inside `DeepResearcherAgent.run()` follows this pattern:

```python
research_content = self.searcher.run(topic)      # ScrapeGraph + Nebius

analysis = self.analyst.run(research_content.content)
report = self.writer.run(analysis.content, stream=True)

```

The `report` iterator streams markdown chunks that are concatenated into the final document (see `run_research()` at lines 16-30 in the source).

## Customizing Roles and Expanding the Crew

New specialized roles can be inserted into either framework by instantiating additional `Agent` objects with domain-specific prompts. For example, adding a "Trend Detector" to the Agno workflow:

```python
trend_detector = Agent(
    model=Nebius(id="deepseek-ai/DeepSeek-V3-0324", api_key=os.getenv("NEBIUS_API_KEY")),
    description="You identify emerging trends from the analyst's summary.",
    instructions=(
        "1. Scan the analysis for repeated keywords and novel concepts.\n"
        "2. Output a list of 3–5 concrete trend statements."
    ),
    markdown=True,
)

# Insert after analyst step:

analysis = self.analyst.run(research_content.content)
trends = trend_detector.run(analysis.content)

# Pass trends to writer:

report = self.writer.run(f"{analysis.content}\n\nTrends:\n{trends.content}", stream=True)

```

This demonstrates how Agno’s workflow architecture supports arbitrary agent expansion while preserving the streaming response pattern. For CrewAI, you would simply add the new agent to the `agents` list and create a corresponding `Task` added to the `tasks` list.

## Summary

- **Define purpose-driven agents** with role-specific descriptions and instructions to shape model behavior without requiring separate fine-tuning.
- **Use sequential processing** via `Process.sequential` in CrewAI or explicit method chaining in Agno to ensure each agent receives validated output from the previous stage.
- **Integrate external tools** such as ScrapeGraph for live data retrieval by attaching tool classes to specific agents (as shown in line 25 of [`deep_researcher_agent/agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/deep_researcher_agent/agents.py)).
- **Extend workflows** by adding new `Agent` instances and inserting them into the task sequence or workflow `run()` method, allowing the same underlying model to serve multiple cognitive roles.
- **Manage secrets** through `.env.example` templates provided in both `starter_ai_agents/crewai_starter/` and `advance_ai_agents/deep_researcher_agent/` directories.

## Frequently Asked Questions

### How do I prevent agents from hallucinating when passing data between stages?

In [`advance_ai_agents/deep_researcher_agent/agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/advance_ai_agents/deep_researcher_agent/agents.py), the analyst and writer agents include explicit instructions (lines 64-71) to extract and use **only** the links and content provided by the previous agent. By constraining the prompt to reference specific variables like `research_content.content` rather than allowing open-ended generation, you ground each stage in the actual output of its predecessor.

### Can I use different LLM providers for different agents in the same crew?

Yes. Both implementations support mixing models. In the CrewAI example, you can pass different `llm` parameters to each `Agent` constructor. In the Agno implementation, each `Agent` instantiation can specify a different model ID or provider (e.g., one agent using `nebius/Qwen/Qwen3-235B-A22B` while another uses `deepseek-ai/DeepSeek-V3-0324`), allowing you to optimize for cost or capability per task.

### What is the difference between CrewAI's `Crew` and Agno's `Workflow`?

CrewAI's `Crew` (used in [`starter_ai_agents/crewai_starter/main.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/starter_ai_agents/crewai_starter/main.py)) handles task sequencing automatically when you provide a list of `Task` objects and set `process=Process.sequential`. Agno's `Workflow` (implemented in [`deep_researcher_agent/agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/deep_researcher_agent/agents.py)) requires you to subclass `Workflow` and manually orchestrate agent execution in a `run()` method, giving you explicit control over data transformation, error handling, and streaming responses between stages.

### How do I add external tools like web scraping to my research crew?

In the Deep Researcher implementation, the `searcher` agent imports `ScrapeGraphTools` from `agno.tools.scrapegraph` and instantiates it at line 25 of [`agents.py`](https://github.com/Arindam200/awesome-ai-apps/blob/main/agents.py). You attach the tool instance to the agent's `tools` parameter. For CrewAI, you would similarly import the appropriate tool class (e.g., `SerperDevTool` or a custom scraper) and pass it to the `tools` list when constructing the `Agent`.