""" This is an example of how to use Arcade with CrewAI. The ArcadeToolManager allows you to handle both authorization and tool execution in a custom way. This example demonstrates how to implement a custom auth handler and a custom tool execute handler. The example assumes the following: 1. You have an Arcade API key and have set the ARCADE_API_KEY environment variable. 2. You have an OpenAI API key and have set the OPENAI_API_KEY environment variable. 3. You have installed the necessary dependencies in the requirements.txt file: `pip install -r requirements.txt` """ from typing import Any from crewai import Agent, Crew, Task from crewai.crews import CrewOutput from crewai.llm import LLM from crewai_arcade import ArcadeToolManager USER_ID = "user@example.com" def custom_auth_flow( manager: ArcadeToolManager, tool_name: str, **tool_input: dict[str, Any] ) -> Any: """Custom auth flow for the ArcadeToolManager This function is called when CrewAI needs to call a tool that requires authorization. Authorization is handled before executing the tool. This function overrides the ArcadeToolManager's default auth flow performed by ArcadeToolManager.authorize_tool """ # Get authorization status auth_response = manager.authorize(tool_name, USER_ID) # If the user is not authorized for the tool, # then we need to handle the authorization before executing the tool if not manager.is_authorized(auth_response.id): print(f"Authorization required for tool: '{tool_name}' with inputs:") for input_name, input_value in tool_input.items(): print(f" {input_name}: {input_value}") # Handle authorization print(f"\nTo authorize, visit: {auth_response.url}") # Block until the user has completed the authorization auth_response = manager.wait_for_auth(auth_response) # Ensure authorization completed successfully if not manager.is_authorized(auth_response.id): raise ValueError(f"Authorization failed for {tool_name}. URL: {auth_response.url}") else: print(f"Authorization already granted for tool: '{tool_name}' with inputs:") for input_name, input_value in tool_input.items(): print(f" {input_name}: {input_value}") def custom_execute_flow( manager: ArcadeToolManager, tool_name: str, **tool_input: dict[str, Any] ) -> Any: """Custom tool execution flow for the ArcadeToolManager This function is called when CrewAI needs to execute a tool after any authorization has been handled. This function overrides the ArcadeToolManager's default tool execution flow performed by ArcadeToolManager.execute_tool """ print(f"Executing tool: '{tool_name}' with inputs:") for input_name, input_value in tool_input.items(): print(f" {input_name}: {input_value}") # Execute the tool response = manager._client.tools.execute( tool_name=tool_name, input=tool_input, user_id=USER_ID, ) # Handle the tool error if it exists tool_error = response.output.error if response.output else None if tool_error: return str(tool_error) # Return the tool output if the tool was executed successfully if response.success: return response.output.value # type: ignore[union-attr] # Return a failure message if the tool was not executed successfully return "Failed to call " + tool_name def custom_tool_executor( manager: ArcadeToolManager, tool_name: str, **tool_input: dict[str, Any] ) -> Any: """Custom tool executor for the ArcadeToolManager ArcadeToolManager's default executor handles authorization and tool execution. This function overrides the default executor to handle authorization and tool execution in a custom way. """ custom_auth_flow(manager, tool_name, **tool_input) return custom_execute_flow(manager, tool_name, **tool_input) def main() -> CrewOutput: manager = ArcadeToolManager( executor=custom_tool_executor, ) tools = manager.get_tools(tools=["Gmail.ListEmails"]) crew_agent = Agent( role="Main Agent", backstory="You are a helpful assistant", goal="Help the user with their requests", tools=tools, allow_delegation=False, verbose=True, llm=LLM(model="gpt-4o"), ) task = Task( description="Get the 5 most recent emails from the user's inbox and summarize them and recommend a response for each.", expected_output="A bulleted list with a one sentence summary of each email and a recommended response to the email.", agent=crew_agent, tools=crew_agent.tools, ) crew = Crew( agents=[crew_agent], tasks=[task], verbose=True, memory=True, ) result = crew.kickoff() return result if __name__ == "__main__": result = main() print("\n\n\n ------------ Result ------------ \n\n\n") print(result)