def _run(
        self,
        inputs: Dict[str, Any],
    ) -> AgentFinish:
        """
        Run inputs including user query and past conversation with agent and get response back
        calls take_next_step function to determine what should be the next step after
        collecting all the inputs and memorized contents
        """
        # Construct a mapping of tool name to tool for easy lookup
        name_to_tool_map = {tool.name: tool for tool in self.agent.tools}

        intermediate_steps: List[AgentAction] = inputs[constants.INTERMEDIATE_STEPS]

        # Let's start tracking the number of iterations and time elapsed
        iterations = 0
        time_elapsed = 0.0
        start_time = time.time()
        # We now enter the agent loop (until it returns something).
        while self._should_continue(iterations, time_elapsed):
            logger.info(f"\n Intermediate steps: {intermediate_steps}\n")
            next_step_output = self.should_answer(inputs=inputs)

            # if next_step_output is None which means should ask agent to answer and take next
            # step
            if not next_step_output:
                next_step_output = self.take_next_step(
                    name_to_tool_map,
                    inputs,
                )

            if isinstance(next_step_output, AgentFinish):
                next_step_output.intermediate_steps = intermediate_steps
                return next_step_output

            # stores action output into the conversation as FunctionMessage, which can be used by
            # OpenAIFunctionsAgent
            if isinstance(next_step_output, AgentAction):
                self.memory.save_conversation(
                    message=str(next_step_output.tool_output),
                    name=next_step_output.tool,
                    conversational_message=f"{next_step_output.tool} with input: "
                    f"{next_step_output.tool_input}",
                    message_type=MessageType.FunctionMessage,
                )

            intermediate_steps.append(next_step_output)
            # update inputs
            inputs[constants.INTERMEDIATE_STEPS] = intermediate_steps
            inputs[constants.CONVERSATION_HISTORY] = self.memory.load_conversation()

            iterations += 1
            time_elapsed = time.time() - start_time

        # force the termination when shouldn't continue
        output = AgentFinish(
            message="Agent stopped due to iteration limit or time limit.",
            log="",
            intermediate_steps=intermediate_steps,
        )
        return output

        Run inputs including user query and past conversation with agent and get response back
        calls take_next_step function to determine what should be the next step after
        collecting all the inputs and memorized contents
        
autochain/chain/base_chain.py