Skip to content
This repository was archived by the owner on Nov 10, 2025. It is now read-only.

Commit 60644e5

Browse files
committed
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.
1 parent fd698be commit 60644e5

File tree

5 files changed

+236
-1
lines changed

5 files changed

+236
-1
lines changed

crewai_tools/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
S3ReaderTool,
77
S3WriterTool,
88
)
9+
from .adapters.zapier_adapter import ZapierActionTool
910
from .tools import (
1011
AIMindTool,
1112
ApifyActorsTool,
@@ -69,4 +70,5 @@
6970
XMLSearchTool,
7071
YoutubeChannelSearchTool,
7172
YoutubeVideoSearchTool,
72-
)
73+
ZapierActionTools,
74+
)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import os
2+
from typing import List
3+
4+
import requests
5+
from crewai.tools import BaseTool
6+
from pydantic import Field, create_model
7+
8+
ACTIONS_URL = "https://actions.zapier.com/api/v2/ai-actions"
9+
10+
11+
class ZapierActionTool(BaseTool):
12+
"""
13+
A tool that wraps a Zapier action
14+
"""
15+
16+
name: str = Field(description="Tool name")
17+
description: str = Field(description="Tool description")
18+
action_id: str = Field(description="Zapier action ID")
19+
api_key: str = Field(description="Zapier API key")
20+
21+
def _run(self, **kwargs) -> str:
22+
"""Execute the Zapier action"""
23+
headers = {"x-api-key": self.api_key, "Content-Type": "application/json"}
24+
25+
instructions = kwargs.pop(
26+
"instructions", "Execute this action with the provided parameters"
27+
)
28+
29+
if not kwargs:
30+
action_params = {"instructions": instructions, "params": {}}
31+
else:
32+
formatted_params = {}
33+
for key, value in kwargs.items():
34+
formatted_params[key] = {
35+
"value": value,
36+
"mode": "guess",
37+
}
38+
action_params = {"instructions": instructions, "params": formatted_params}
39+
40+
print(f"Executing action {self.action_id} with payload: {action_params}")
41+
42+
execute_url = f"{ACTIONS_URL}/{self.action_id}/execute/"
43+
response = requests.request(
44+
"POST", execute_url, headers=headers, json=action_params
45+
)
46+
47+
response.raise_for_status()
48+
49+
return response.json()
50+
51+
52+
class ZapierActionsAdapter:
53+
"""
54+
Adapter for Zapier Actions
55+
"""
56+
57+
api_key: str
58+
59+
def __init__(self, api_key: str = None):
60+
self.api_key = api_key or os.getenv("ZAPIER_API_KEY")
61+
if not self.api_key:
62+
raise ValueError("Zapier Actions API key is required")
63+
64+
def get_zapier_actions(self):
65+
headers = {
66+
"x-api-key": self.api_key,
67+
}
68+
response = requests.request("GET", ACTIONS_URL, headers=headers)
69+
response.raise_for_status()
70+
71+
response_json = response.json()
72+
return response_json
73+
74+
def tools(self) -> List[BaseTool]:
75+
"""Convert Zapier actions to BaseTool instances"""
76+
actions_response = self.get_zapier_actions()
77+
print("actions_response", actions_response)
78+
tools = []
79+
80+
for action in actions_response.get("results", []):
81+
tool_name = (
82+
action["meta"]["action_label"]
83+
.replace(" ", "_")
84+
.replace(":", "")
85+
.lower()
86+
)
87+
88+
params = action.get("params", {})
89+
args_fields = {}
90+
91+
args_fields["instructions"] = (
92+
str,
93+
Field(description="Instructions for how to execute this action"),
94+
)
95+
96+
for param_name, param_info in params.items():
97+
field_type = (
98+
str # Default to string, could be enhanced based on param_info
99+
)
100+
field_description = (
101+
param_info.get("description", "")
102+
if isinstance(param_info, dict)
103+
else ""
104+
)
105+
args_fields[param_name] = (
106+
field_type,
107+
Field(description=field_description),
108+
)
109+
110+
args_schema = create_model(f"{tool_name.title()}Schema", **args_fields)
111+
112+
tool = ZapierActionTool(
113+
name=tool_name,
114+
description=action["description"],
115+
action_id=action["id"],
116+
api_key=self.api_key,
117+
args_schema=args_schema,
118+
)
119+
tools.append(tool)
120+
121+
return tools

crewai_tools/tools/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,4 @@
7777
YoutubeChannelSearchTool,
7878
)
7979
from .youtube_video_search_tool.youtube_video_search_tool import YoutubeVideoSearchTool
80+
from .zapier_action_tool.zapier_action_tool import ZapierActionTools
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Zapier Action Tools
2+
3+
## Description
4+
5+
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.
6+
7+
## Installation
8+
9+
Install the crewai_tools package by executing the following command in your terminal:
10+
11+
```shell
12+
uv pip install 'crewai[tools]'
13+
```
14+
15+
## Example
16+
17+
To utilize the ZapierActionTools for different use cases, follow these examples:
18+
19+
```python
20+
from crewai_tools import ZapierActionTools
21+
from crewai import Agent
22+
23+
# Get all available Zapier actions you are connected to.
24+
tools = ZapierActionTools(
25+
zapier_api_key="your-zapier-api-key"
26+
)
27+
28+
# Or specify only certain actions you want to use
29+
tools = ZapierActionTools(
30+
zapier_api_key="your-zapier-api-key",
31+
action_list=["gmail_find_email", "slack_send_message", "google_sheets_create_row"]
32+
)
33+
34+
# Adding the tools to an agent
35+
zapier_agent = Agent(
36+
name="zapier_agent",
37+
role="You are a helpful assistant that can automate tasks using Zapier integrations.",
38+
llm="gpt-4o-mini",
39+
tools=tools,
40+
goal="Automate workflows and integrate with various applications",
41+
backstory="You are a Zapier automation expert that helps users connect and automate their favorite apps.",
42+
verbose=True,
43+
)
44+
45+
# Example usage
46+
result = zapier_agent.kickoff(
47+
"Find emails from john@example.com in Gmail"
48+
)
49+
```
50+
51+
## Arguments
52+
53+
- `zapier_api_key` : Your Zapier API key for authentication. Can also be set via `ZAPIER_API_KEY` environment variable. (Required)
54+
- `action_list` : A list of specific Zapier action names to include. If not provided, all available actions will be returned. (Optional)
55+
56+
## Environment Variables
57+
58+
You can set your Zapier API key as an environment variable instead of passing it directly:
59+
60+
```bash
61+
export ZAPIER_API_KEY="your-zapier-api-key"
62+
```
63+
64+
Then use the tool without explicitly passing the API key:
65+
66+
```python
67+
from crewai_tools import ZapierActionTools
68+
69+
# API key will be automatically loaded from environment
70+
tools = ZapierActionTools(
71+
action_list=["gmail_find_email", "slack_send_message"]
72+
)
73+
```
74+
75+
## Getting Your Zapier API Key
76+
77+
1. Log in to your Zapier account
78+
2. Go to https://zapier.com/app/developer/
79+
3. Create a new app or use an existing one
80+
4. Navigate to the "Authentication" section
81+
5. Copy your API key
82+
83+
## Available Actions
84+
85+
The tool will dynamically discover all available Zapier actions associated with your API key. Common actions include:
86+
87+
- Gmail operations (find emails, send emails)
88+
- Slack messaging
89+
- Google Sheets operations
90+
- Calendar events
91+
- And hundreds more depending on your Zapier integrations
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import os
2+
from typing import List, Optional
3+
from crewai.tools import BaseTool
4+
from crewai_tools.adapters.zapier_adapter import ZapierActionsAdapter
5+
6+
7+
def ZapierActionTools(
8+
zapier_api_key: Optional[str] = None, action_list: Optional[List[str]] = None
9+
) -> List[BaseTool]:
10+
if zapier_api_key is None:
11+
zapier_api_key = os.getenv("ZAPIER_API_KEY")
12+
if zapier_api_key is None:
13+
raise ValueError("ZAPIER_API_KEY is not set")
14+
adapter = ZapierActionsAdapter(zapier_api_key)
15+
all_tools = adapter.tools()
16+
17+
if action_list is None:
18+
return all_tools
19+
20+
return [tool for tool in all_tools if tool.name in action_list]

0 commit comments

Comments
 (0)