mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-09 08:08:32 +00:00
feat: add ZapierActionTool and ZapierActionsAdapter for integrating with Zapier actions (#311)
* feat: add ZapierActionTool and ZapierActionsAdapter for integrating with Zapier actions - Introduced ZapierActionTool to execute Zapier actions with dynamic parameter handling. - Added ZapierActionsAdapter to fetch available Zapier actions and convert them into BaseTool instances. - Updated __init__.py files to include new tools and ensure proper imports. - Created README.md for ZapierActionTools with installation instructions and usage examples. * fix: restore ZapierActionTool import and enhance logging in Zapier adapter - Reintroduced the import of ZapierActionTool in __init__.py for proper accessibility. - Added logging for error handling in ZapierActionsAdapter to improve debugging. - Updated ZapierActionTools factory function to include logging for missing API key.
This commit is contained in:
@@ -69,4 +69,6 @@ from .tools import (
|
||||
XMLSearchTool,
|
||||
YoutubeChannelSearchTool,
|
||||
YoutubeVideoSearchTool,
|
||||
)
|
||||
ZapierActionTools,
|
||||
)
|
||||
from .adapters.zapier_adapter import ZapierActionTool
|
||||
|
||||
122
src/crewai_tools/adapters/zapier_adapter.py
Normal file
122
src/crewai_tools/adapters/zapier_adapter.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import os
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
import requests
|
||||
from crewai.tools import BaseTool
|
||||
from pydantic import Field, create_model
|
||||
|
||||
ACTIONS_URL = "https://actions.zapier.com/api/v2/ai-actions"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ZapierActionTool(BaseTool):
|
||||
"""
|
||||
A tool that wraps a Zapier action
|
||||
"""
|
||||
|
||||
name: str = Field(description="Tool name")
|
||||
description: str = Field(description="Tool description")
|
||||
action_id: str = Field(description="Zapier action ID")
|
||||
api_key: str = Field(description="Zapier API key")
|
||||
|
||||
def _run(self, **kwargs) -> str:
|
||||
"""Execute the Zapier action"""
|
||||
headers = {"x-api-key": self.api_key, "Content-Type": "application/json"}
|
||||
|
||||
instructions = kwargs.pop(
|
||||
"instructions", "Execute this action with the provided parameters"
|
||||
)
|
||||
|
||||
if not kwargs:
|
||||
action_params = {"instructions": instructions, "params": {}}
|
||||
else:
|
||||
formatted_params = {}
|
||||
for key, value in kwargs.items():
|
||||
formatted_params[key] = {
|
||||
"value": value,
|
||||
"mode": "guess",
|
||||
}
|
||||
action_params = {"instructions": instructions, "params": formatted_params}
|
||||
|
||||
execute_url = f"{ACTIONS_URL}/{self.action_id}/execute/"
|
||||
response = requests.request(
|
||||
"POST", execute_url, headers=headers, json=action_params
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
||||
|
||||
class ZapierActionsAdapter:
|
||||
"""
|
||||
Adapter for Zapier Actions
|
||||
"""
|
||||
|
||||
api_key: str
|
||||
|
||||
def __init__(self, api_key: str = None):
|
||||
self.api_key = api_key or os.getenv("ZAPIER_API_KEY")
|
||||
if not self.api_key:
|
||||
logger.error("Zapier Actions API key is required")
|
||||
raise ValueError("Zapier Actions API key is required")
|
||||
|
||||
def get_zapier_actions(self):
|
||||
headers = {
|
||||
"x-api-key": self.api_key,
|
||||
}
|
||||
response = requests.request("GET", ACTIONS_URL, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
response_json = response.json()
|
||||
return response_json
|
||||
|
||||
def tools(self) -> List[BaseTool]:
|
||||
"""Convert Zapier actions to BaseTool instances"""
|
||||
actions_response = self.get_zapier_actions()
|
||||
tools = []
|
||||
|
||||
for action in actions_response.get("results", []):
|
||||
tool_name = (
|
||||
action["meta"]["action_label"]
|
||||
.replace(" ", "_")
|
||||
.replace(":", "")
|
||||
.lower()
|
||||
)
|
||||
|
||||
params = action.get("params", {})
|
||||
args_fields = {}
|
||||
|
||||
args_fields["instructions"] = (
|
||||
str,
|
||||
Field(description="Instructions for how to execute this action"),
|
||||
)
|
||||
|
||||
for param_name, param_info in params.items():
|
||||
field_type = (
|
||||
str # Default to string, could be enhanced based on param_info
|
||||
)
|
||||
field_description = (
|
||||
param_info.get("description", "")
|
||||
if isinstance(param_info, dict)
|
||||
else ""
|
||||
)
|
||||
args_fields[param_name] = (
|
||||
field_type,
|
||||
Field(description=field_description),
|
||||
)
|
||||
|
||||
args_schema = create_model(f"{tool_name.title()}Schema", **args_fields)
|
||||
|
||||
tool = ZapierActionTool(
|
||||
name=tool_name,
|
||||
description=action["description"],
|
||||
action_id=action["id"],
|
||||
api_key=self.api_key,
|
||||
args_schema=args_schema,
|
||||
)
|
||||
tools.append(tool)
|
||||
|
||||
return tools
|
||||
@@ -77,3 +77,4 @@ from .youtube_channel_search_tool.youtube_channel_search_tool import (
|
||||
YoutubeChannelSearchTool,
|
||||
)
|
||||
from .youtube_video_search_tool.youtube_video_search_tool import YoutubeVideoSearchTool
|
||||
from .zapier_action_tool.zapier_action_tool import ZapierActionTools
|
||||
|
||||
91
src/crewai_tools/tools/zapier_action_tool/README.md
Normal file
91
src/crewai_tools/tools/zapier_action_tool/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Zapier Action Tools
|
||||
|
||||
## Description
|
||||
|
||||
This tool enables CrewAI agents to interact with Zapier actions, allowing them to automate workflows and integrate with hundreds of applications through Zapier's platform. The tool dynamically creates BaseTool instances for each available Zapier action, making it easy to incorporate automation into your AI workflows.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the crewai_tools package by executing the following command in your terminal:
|
||||
|
||||
```shell
|
||||
uv pip install 'crewai[tools]'
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
To utilize the ZapierActionTools for different use cases, follow these examples:
|
||||
|
||||
```python
|
||||
from crewai_tools import ZapierActionTools
|
||||
from crewai import Agent
|
||||
|
||||
# Get all available Zapier actions you are connected to.
|
||||
tools = ZapierActionTools(
|
||||
zapier_api_key="your-zapier-api-key"
|
||||
)
|
||||
|
||||
# Or specify only certain actions you want to use
|
||||
tools = ZapierActionTools(
|
||||
zapier_api_key="your-zapier-api-key",
|
||||
action_list=["gmail_find_email", "slack_send_message", "google_sheets_create_row"]
|
||||
)
|
||||
|
||||
# Adding the tools to an agent
|
||||
zapier_agent = Agent(
|
||||
name="zapier_agent",
|
||||
role="You are a helpful assistant that can automate tasks using Zapier integrations.",
|
||||
llm="gpt-4o-mini",
|
||||
tools=tools,
|
||||
goal="Automate workflows and integrate with various applications",
|
||||
backstory="You are a Zapier automation expert that helps users connect and automate their favorite apps.",
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
# Example usage
|
||||
result = zapier_agent.kickoff(
|
||||
"Find emails from john@example.com in Gmail"
|
||||
)
|
||||
```
|
||||
|
||||
## Arguments
|
||||
|
||||
- `zapier_api_key` : Your Zapier API key for authentication. Can also be set via `ZAPIER_API_KEY` environment variable. (Required)
|
||||
- `action_list` : A list of specific Zapier action names to include. If not provided, all available actions will be returned. (Optional)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
You can set your Zapier API key as an environment variable instead of passing it directly:
|
||||
|
||||
```bash
|
||||
export ZAPIER_API_KEY="your-zapier-api-key"
|
||||
```
|
||||
|
||||
Then use the tool without explicitly passing the API key:
|
||||
|
||||
```python
|
||||
from crewai_tools import ZapierActionTools
|
||||
|
||||
# API key will be automatically loaded from environment
|
||||
tools = ZapierActionTools(
|
||||
action_list=["gmail_find_email", "slack_send_message"]
|
||||
)
|
||||
```
|
||||
|
||||
## Getting Your Zapier API Key
|
||||
|
||||
1. Log in to your Zapier account
|
||||
2. Go to https://zapier.com/app/developer/
|
||||
3. Create a new app or use an existing one
|
||||
4. Navigate to the "Authentication" section
|
||||
5. Copy your API key
|
||||
|
||||
## Available Actions
|
||||
|
||||
The tool will dynamically discover all available Zapier actions associated with your API key. Common actions include:
|
||||
|
||||
- Gmail operations (find emails, send emails)
|
||||
- Slack messaging
|
||||
- Google Sheets operations
|
||||
- Calendar events
|
||||
- And hundreds more depending on your Zapier integrations
|
||||
@@ -0,0 +1,33 @@
|
||||
import os
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
from crewai.tools import BaseTool
|
||||
from crewai_tools.adapters.zapier_adapter import ZapierActionsAdapter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def ZapierActionTools(
|
||||
zapier_api_key: Optional[str] = None, action_list: Optional[List[str]] = None
|
||||
) -> List[BaseTool]:
|
||||
"""Factory function that returns Zapier action tools.
|
||||
|
||||
Args:
|
||||
zapier_api_key: The API key for Zapier.
|
||||
action_list: Optional list of specific tool names to include.
|
||||
|
||||
Returns:
|
||||
A list of Zapier action tools.
|
||||
"""
|
||||
if zapier_api_key is None:
|
||||
zapier_api_key = os.getenv("ZAPIER_API_KEY")
|
||||
if zapier_api_key is None:
|
||||
logger.error("ZAPIER_API_KEY is not set")
|
||||
raise ValueError("ZAPIER_API_KEY is not set")
|
||||
adapter = ZapierActionsAdapter(zapier_api_key)
|
||||
all_tools = adapter.tools()
|
||||
|
||||
if action_list is None:
|
||||
return all_tools
|
||||
|
||||
return [tool for tool in all_tools if tool.name in action_list]
|
||||
Reference in New Issue
Block a user