How to pass response from an agent in a chain as a parameter to Exa tool that is used by another agent?

Code

I have a crew of 3 agents with 3 tasks and 1 tool as follows:

# crews.py
from utils.agents import XxxxxAgents
from utils.tasks import XxxxxTasks
from utils.tools import XxxxxTools
from crewai import Crew, Process
import streamlit as st
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    api_key=st.secrets["OPENAI_API_KEY"],
)

class XxxxxCrew:
    def __init__(self, input_a: str, input_b: str):
        agents = XxxxxAgents()
        tasks = XxxxxTasks()

        self.agent_1 = agents.agent_1()
        self.agent_2 = agents.agent_2()
        self.agent_3 = agents.agent_3()

        self.task_1 = tasks.task_1(self.agent_1, input_a)
        self.task_2 = tasks.task_2(self.agent_2)
        self.task_3 = tasks.task_3(self.agent_3, input_b)

        self.crew = Crew(
            agents=[
                self.agent_1,
                self.agent_2,
                self.agent_3,
            ],
            tasks=[
                self.task_1,
                self.task_2,
                self.task_3,
            ],
            manager_llm=llm,
            process=Process.sequential,
            verbose=True,
        )

    def kickoff(self):
        return self.crew.kickoff() 
# agents.py
from crewai import Agent
from utils.tools import XxxxxTools

class XxxxxAgents:
    def agent_1(self):
        return Agent(
            role="xxxxx",
            goal="xxxxx",
            backstory="xxxxx",
            allow_delegation=True,
            verbose=True,
        )

    def agent_2(self):
        return Agent(
            role="xxxxx",
            goal="xxxxx",
            backstory="xxxxx",
            allow_delegation=True,
            verbose=True,
        )

    def agent_3(self):
        return Agent(
            role="xxxxx",
            goal="xxxxx",
            backstory="xxxxx",
            tools=xxxxxTools.tools(),
            allow_delegation=False,
            verbose=True,
        )
# tasks.py
from crewai import Task

class XxxxxTasks:
    def task_1(self, agent, input_a):
        return Task(
            description="xxxxx",
            expected_output="xxxxx",
            agent=agent,
        )

    def task_2(self, agent):
        return Task(
            description="xxxxx",
            expected_output="xxxxx",
            agent=agent,
        )

    def task_3(self, agent, topic):
        return Task(
            description="xxxxx",
            expected_output="xxxxx",
            agent=agent,
        )
# tools.py
from crewai_tools import tool
from exa_py import Exa
import streamlit as st

class XxxxxTools:
    def _exa():
        return Exa(api_key=st.secrets["EXA_API_KEY"])

    @tool
    def exa_search_and_get_contents(input_b, input_c):
        return XxxxxTools._exa().search_and_contents(
            query=input_b,
            type="neural",
            include_domains=input_c,
            use_autoprompt=False,
            num_results=3,
            text=True,
            summary=True,
        )

    def tools():
        return [XxxxxTools.exa_search_and_get_contents]

Problem

The problem is that I’m not able to deterministically get the input_c from the agent_2 and pass it to the tool exa_search_and_get_contents. Both input_a and input_b are given by a user before the crew is kicked off. But the input_c is an answer that the agent_2 should give. So, I get input_c correctly, but I don’t know how to pass it to the tool exa_search_and_get_contents.

Currently, I’m getting the following error:

I encountered an error while trying to use the tool. This was the error: XxxxxTools.exa_search_and_get_contents() missing 2 required positional arguments: ‘input_b’ and ‘input_c’.

You could try and pass context from each task to the next or from multiple task results.

 @task
    def reporting_task(self) -> Task:
        return Task(
            config=self.tasks_config['reporting_task'],
            agent=self.reporting_analyst(),
            context=[self.research_task(), self.ideas_task()],
            output_file='report.md'
        )

Try telling it in the task expected output to use a simple dictionary for the results you want to pass in the context.
These things are not very good at repeatable precision. Create as much structure as you can to help them.

Hey Rok,

I hope you are well.

I took a look at your problem and think there could be an easier way around it

Instead of manually passing data, you should explore using agent memory and shared memory space. This will allow agent 3 to simply query agent 2’s memory for the input_c value and use it in the tool. Here’s how it could look conceptually:

# Define agent_2 with memory
def agent_2(self):
    return Agent(
        role="xxxxx",
        goal="xxxxx",
        backstory="xxxxx",
        allow_delegation=True,
        verbose=True,
        memory=True,  # Enable memory
    )

# Define agent_3 with access to shared memory
def agent_3(self):
    return Agent(
        role="xxxxx",
        goal="xxxxx",
        backstory="xxxxx",
        tools=XxxxxTools.tools(),
        allow_delegation=False,
        verbose=True,
        memory=True,  # Enable memory access
    )

Conclusion:

By enabling memory for your agents, you’re not only simplifying the process, but you’re also embracing the core philosophy of CrewAI: making agents work collaboratively and efficiently as a real-world team would. This way, agent 2’s output becomes part of the shared memory that agent 3 can directly pull from, bypassing the need for manual data handoffs.

Please let me know if this helped.

2 Likes

True. And if Im correct the context I recommended needs memory enabled as a dependency. But I could be wrong :man_shrugging:

@jklre @moto Thanks for your thoughts. The solution, which so far looks reliable, is simply using the EXASearchTool class from the crew_tools SDK as follows:

from crewai_tools import EXASearchTool
import streamlit as st

exa_tool = EXASearchTool(
    api_key=st.secrets["EXA_API_KEY"],
)

I thought this wouldn’t yield good responses because when I was testing Exa in the browser dashboard, I needed to set the include_domains parameter in order to get good responses. With such initialization of Exa, I basically set only the API key and not other parameters, yet the Crew returns satisfying responses.

It looks like agents can figure out how to get good responses from Exa on their own. The only downside is that sometimes agents need to repeat tasks to figure out what input to pass to Exa to get good output.

2 Likes

@ScarletAI I couldn’t tag you in the previous reply because “new users can only mention 2 users in a post”. Everything being said in the previous reply applies to you too. :slight_smile:

2 Likes