<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Syed Kaifuddin</title>
    <description>The latest articles on DEV Community by Syed Kaifuddin (@syed_kaif777).</description>
    <link>https://dev.to/syed_kaif777</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3804383%2F690ca77d-2a3a-4fe8-af3e-eecdffea0680.jpg</url>
      <title>DEV Community: Syed Kaifuddin</title>
      <link>https://dev.to/syed_kaif777</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/syed_kaif777"/>
    <language>en</language>
    <item>
      <title>Building a Multi-Agent AI Market Research Tool with CrewAI &amp; Groq</title>
      <dc:creator>Syed Kaifuddin</dc:creator>
      <pubDate>Tue, 03 Mar 2026 17:56:01 +0000</pubDate>
      <link>https://dev.to/syed_kaif777/title-building-a-multi-agent-ai-market-research-tool-with-crewai-groq-22na</link>
      <guid>https://dev.to/syed_kaif777/title-building-a-multi-agent-ai-market-research-tool-with-crewai-groq-22na</guid>
      <description>&lt;p&gt;I recently built a multi-agent AI system that takes a product idea and generates a full market research report using 5 specialized AI agents — all running on &lt;strong&gt;Groq's free tier&lt;/strong&gt;. No credit card. No paid API.&lt;/p&gt;

&lt;p&gt;But the journey wasn't smooth. I hit 7 different errors before it worked. This article covers both — &lt;strong&gt;what I built and how I fixed everything that broke.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Market Research Crew&lt;/strong&gt; — a multi-agent AI pipeline where 5 autonomous agents collaborate sequentially to research any product idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📊 &lt;strong&gt;Market Research Specialist&lt;/strong&gt; — industry size, trends, opportunities&lt;/li&gt;
&lt;li&gt;🕵️ &lt;strong&gt;Competitive Intelligence Analyst&lt;/strong&gt; — competitors, pricing, market share&lt;/li&gt;
&lt;li&gt;👥 &lt;strong&gt;Customer Insights Researcher&lt;/strong&gt; — personas, pain points, needs&lt;/li&gt;
&lt;li&gt;🗺️ &lt;strong&gt;Product Strategy Advisor&lt;/strong&gt; — positioning, feature roadmap&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Business Analyst&lt;/strong&gt; — synthesizes everything into recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user types a product idea into a &lt;strong&gt;Streamlit UI&lt;/strong&gt;, hits run, and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;UI updates in real time&lt;/strong&gt; showing each agent's status&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;IDE terminal streams live output&lt;/strong&gt; — agent thoughts, tool calls, completions&lt;/li&gt;
&lt;li&gt;5 markdown reports are generated and displayed in tabs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/syed-kaif07/market-research-crew" rel="noopener noreferrer"&gt;https://github.com/syed-kaif07/market-research-crew&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CrewAI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-agent orchestration framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Groq&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free LLM API (insanely fast)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LLaMA 3.3 70B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The language model powering all agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streamlit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python 3.13&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;uv&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast package manager&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🏗️ Architecture
&lt;/h2&gt;

&lt;p&gt;The most interesting part of this project is how the &lt;strong&gt;UI and terminal work simultaneously&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User types idea in Streamlit
         │
         ▼
streamlit_app.py
  └── subprocess.Popen(stdout=None)  ← key: inherits parent terminal
         │
         ▼
main.py
  ├── Prints colored agent banners to terminal
  ├── Hooks _TaskTracker into CrewAI's task_callback
  └── Calls crew.kickoff()
         │
         ▼
CrewAI runs 5 agents sequentially
  └── Each agent writes output to output/*.md
         │
streamlit_app.py polls output/*.md every 4 seconds
  └── Updates agent cards: QUEUED → RUNNING → DONE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic is one line in &lt;code&gt;streamlit_app.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;python_exe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;main_script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--product-idea&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product_idea&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# ← inherits parent terminal = live output
&lt;/span&gt;    &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# ← errors visible too
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By setting &lt;code&gt;stdout=None&lt;/code&gt;, the child process inherits the parent's terminal handles. So everything CrewAI prints — agent thoughts, tool calls, our colored banners — all stream live to the IDE terminal while Streamlit polls for completed output files.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 How CrewAI Works
&lt;/h2&gt;

&lt;p&gt;CrewAI uses decorators to define agents and tasks cleanly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@CrewBase&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketResearchCrew&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;agents_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config/agents.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;tasks_config&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config/tasks.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="nd"&gt;@agent&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;market_research_specialist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_research_specialist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;competitive_intelligence_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;competitive_intelligence_task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;market_research_task&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;  &lt;span class="c1"&gt;# gets Agent 1's output
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@crew&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# one by one
&lt;/span&gt;            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;# prints agent thoughts
&lt;/span&gt;            &lt;span class="n"&gt;max_rpm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="c1"&gt;# respects free tier limits
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent configs live in YAML files — clean separation of concerns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# agents.yaml&lt;/span&gt;
&lt;span class="na"&gt;market_research_specialist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Market Research Specialist&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Analyze market size, trends, and opportunities for {product_idea}&lt;/span&gt;
  &lt;span class="na"&gt;backstory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;You are an expert market researcher with 10 years of experience...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🖥️ Live Terminal Logging
&lt;/h2&gt;

&lt;p&gt;To show live agent progress in the terminal, I hooked into CrewAI's &lt;code&gt;task_callback&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_TaskTracker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_task_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_output&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Called automatically by CrewAI after every task
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent_start&lt;/span&gt;
        &lt;span class="nf"&gt;_agent_done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# prints ✓ AGENT X COMPLETE
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AGENTS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;_agent_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# prints &amp;gt;&amp;gt; AGENT X+1 STARTING
&lt;/span&gt;
&lt;span class="c1"&gt;# Attach to crew before kickoff
&lt;/span&gt;&lt;span class="n"&gt;crew_obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_task_complete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result in terminal looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=================================================================
        MARKET RESEARCH CREW - AGENT PIPELINE
        Powered by CrewAI x Groq x LLaMA 3.3 70B
=================================================================

  Research Topic: future of Gen AI in health sector

  AGENT PIPELINE QUEUE:
  1. 📊  Market Research Specialist        [ QUEUED ]
  2. 🕵️  Competitive Intelligence Analyst  [ QUEUED ]
  ...

-----------------------------------------------------------------
  &amp;gt;&amp;gt; AGENT 1/5 STARTING  📊  Market Research Specialist
  Time: 14:21:27
-----------------------------------------------------------------

  ✓ AGENT 1/5 COMPLETE  📊  Market Research Specialist
  Time taken: 43.2s
  Progress: [█░░░░] 1/5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🐛 The Errors (The Real Story)
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. Nothing worked on the first try.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error 1 — &lt;code&gt;AttributeError: st.session_state has no attribute "start_time"&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; Streamlit reruns the entire script on every user interaction. If a &lt;code&gt;session_state&lt;/code&gt; key isn't initialized upfront, accessing it on a fresh rerun throws &lt;code&gt;AttributeError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Initialize ALL session state keys at the top of the script before any logic runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;_DEFAULTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;running&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;product_idea&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# ← was missing
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_val&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_DEFAULTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_key&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_val&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; Always initialize session state with a defaults dict. Never access a key before setting it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Error 2 — &lt;code&gt;ImportError: Fallback to LiteLLM is not available&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; &lt;code&gt;pyproject.toml&lt;/code&gt; had &lt;code&gt;crewai[tools]==1.9.3&lt;/code&gt; hardcoded. That old version of crewai couldn't find LiteLLM properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Update &lt;code&gt;pyproject.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Before&lt;/span&gt;
&lt;span class="py"&gt;"crewai[tools]=&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.9&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="c"&gt;# After&lt;/span&gt;
&lt;span class="py"&gt;"crewai[tools,litellm]&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.10&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then sync:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; &lt;span class="nt"&gt;--prerelease&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;allow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Error 3 — openai version conflict
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; &lt;code&gt;litellm&lt;/code&gt; needed &lt;code&gt;openai&amp;gt;=2.8.0&lt;/code&gt; but &lt;code&gt;crewai 1.9.3&lt;/code&gt; needed &lt;code&gt;openai==1.83.0&lt;/code&gt;. They couldn't coexist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Upgrading crewai to v1.10+ resolved this — the newer version aligned with litellm's openai requirement.&lt;/p&gt;




&lt;h3&gt;
  
  
  Error 4 — &lt;code&gt;uv sync&lt;/code&gt; keeps rolling back versions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; &lt;code&gt;uv&lt;/code&gt; respects &lt;code&gt;pyproject.toml&lt;/code&gt; strictly. Even after manually installing newer packages, &lt;code&gt;uv sync&lt;/code&gt; would revert everything back to the pinned versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; The &lt;code&gt;pyproject.toml&lt;/code&gt; pin is the source of truth. Fix it there first, then sync.&lt;/p&gt;




&lt;h3&gt;
  
  
  Error 5 — TOML parse error
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;missing comma between array elements, expected `,`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; Added &lt;code&gt;"crewai[tools,litellm]&amp;gt;=1.10.1b1"&lt;/code&gt; without a trailing comma in the dependencies array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; TOML arrays need a comma after every element including the last one before &lt;code&gt;]&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Error 6 — &lt;code&gt;No solution found: crewai[tools]&amp;gt;=1.10.1 unsatisfiable&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; &lt;code&gt;crewai 1.10.1&lt;/code&gt; stable doesn't exist yet — only &lt;code&gt;1.10.1b1&lt;/code&gt; (beta).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use &lt;code&gt;&amp;gt;=1.10.1b1&lt;/code&gt; and add &lt;code&gt;--prerelease=allow&lt;/code&gt; to uv commands.&lt;/p&gt;




&lt;h3&gt;
  
  
  Error 7 — &lt;code&gt;git push&lt;/code&gt; rejected
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: src refspec main does not match any
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; I was running git commands from inside &lt;code&gt;src/market_research_crew/&lt;/code&gt; instead of the project root.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../..   &lt;span class="c"&gt;# go to project root first&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Key Lessons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;pyproject.toml&lt;/code&gt; is the source of truth&lt;/strong&gt;&lt;br&gt;
When using &lt;code&gt;uv&lt;/code&gt;, always fix version pins in &lt;code&gt;pyproject.toml&lt;/code&gt; first. Manual pip installs get overridden on next &lt;code&gt;uv sync&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Streamlit session state must be initialized upfront&lt;/strong&gt;&lt;br&gt;
Use a &lt;code&gt;_DEFAULTS&lt;/code&gt; dict pattern. Any key you access must be initialized before Streamlit reruns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;stdout=None&lt;/code&gt; enables live terminal streaming&lt;/strong&gt;&lt;br&gt;
When spawning subprocesses, &lt;code&gt;stdout=None&lt;/code&gt; inherits the parent terminal — much better for debugging than redirecting to a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. CrewAI's &lt;code&gt;task_callback&lt;/code&gt; is powerful&lt;/strong&gt;&lt;br&gt;
Hooking into &lt;code&gt;task_callback&lt;/code&gt; lets you track exactly when each agent completes without modifying CrewAI internals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Dependency conflicts need a root cause fix&lt;/strong&gt;&lt;br&gt;
Installing packages manually is a band-aid. The real fix is always the version constraint in your project config file.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/syed-kaif07/market-research-crew.git
&lt;span class="nb"&gt;cd &lt;/span&gt;market-research-crew

pip &lt;span class="nb"&gt;install &lt;/span&gt;uv
uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--prerelease&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;allow

&lt;span class="c"&gt;# Add your free Groq API key to .env&lt;/span&gt;
&lt;span class="c"&gt;# GROQ_API_KEY=your_key_here&lt;/span&gt;
&lt;span class="c"&gt;# MODEL=groq/llama-3.3-70b-versatile&lt;/span&gt;

python &lt;span class="nt"&gt;-m&lt;/span&gt; streamlit run src/market_research_crew/streamlit_app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get a free Groq API key at &lt;a href="https://console.groq.com" rel="noopener noreferrer"&gt;console.groq.com&lt;/a&gt; — no credit card needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add PDF export for the full report&lt;/li&gt;
&lt;li&gt;Add web search tools so agents pull live data&lt;/li&gt;
&lt;li&gt;Let users choose between different LLMs from the UI&lt;/li&gt;
&lt;li&gt;Build a second crew for content writing or SEO&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you found this useful or have questions, drop a comment below. And if you're working on something similar with CrewAI, I'd love to see it!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/syed-kaif07" rel="noopener noreferrer"&gt;Syed Kaifuddin&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
