How to build a "Chat with Attio" AI Slackbot

Introduction #
In this guide, we'll walk you through creating a Slackbot that uses AI to answer questions about Attio deals. This bot leverages the power of CrewAI, Attio's API, and OpenAI's language models to provide intelligent responses to deal-related queries.
By the end of this tutorial, you'll have an AI Slackbot that can fetch and answer queries about your Attio deals data.
Getting Started #
To begin, fork this template by clicking "Use Template" below:
Setting Up #
Slack App

- Go to the Slack Apps dashboard and create a new app.
- In your app's settings, navigate to the "Basic Information" page.
- Scroll down to the "App-Level Tokens" section.
- Click on "Generate Token and Scopes" to create a new app-level token.
- Provide a name for your token.
- Add the following scopes for your app:
- connections:write (for Socket Mode)
- Click "Generate" to create the token. This is your SLACK_APP_TOKEN: Your app token - it should start with xapp
- Navigate to "OAuth & Permissions" and find your "Bot User OAuth Token". This is your SLACK_BOT_TOKEN: Your bot user OAuth token - it should start with xoxb
- For your Bot Token, set the following permissions:

In Replit, go to the Secrets tab (Tools > Secrets) and add the credentials to your secrets within SLACK_APP_TOKEN and SLACK_BOT_TOKEN respectively.
If you want a character for your new Slack App, feel free to download this little guy:

Attio Private Key

- Log in to your Attio account and navigate to the Workspace Settings.
- Head to the Developers settings.
- Click the blue Create a new integration
- Under Scopes be sure to give Read permissions under:
- User management
- Public Collections
- Records
- Object Configuration
- List Entries
- List Configuration
- Notes
- Tasks
- Then open the Access tokens section and copy your new Attio Access Token.
- In Replit, add this token to the Secrets tab as ATTIO_TOKEN.
OpenAI API Key

- Log in to the OpenAI developer platform.
- Navigate to API keys and create a new secret key.
- Copy the secret key and add it to Replit's Secrets tab as OPENAI_API_KEY.
Understanding the Code #
CrewAI Concepts
This project uses CrewAI, a framework for creating AI agents that work together. Here are the key concepts:
- Tools: Functions that agents can use to interact with external systems or perform specific tasks.
- Agents: AI entities with defined roles and goals.
- Tasks: Specific jobs assigned to agents.
- Crew: A group of agents working together to accomplish a goal.
To learn more about CrewAI, be sure to visit their documentation.
Fetching Deal Data
One unique feature of this implementation is how it fetches deal data from Attio. Let's look at the relevant tool:
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class ListDealsTool(BaseTool):
name: str = "List Deals"
description: str = "Fetches deals from Attio based on given filters and sorts"
args_schema: type[BaseModel] = ListDealsToolInput
def _run(self, filter: Optional[Filter] = None, sorts: List[Sort] = ..., limit: int = 5, offset: int = 0) -> List[Dict]:
url = "https://api.attio.com/v2/objects/deals/records/query"
headers = {
"accept": "application/json",
"authorization": f"Bearer {attio_token}",
"content-type": "application/json"
}
payload = {
"sorts": [sort.model_dump() for sort in sorts],
"limit": limit,
"offset": offset
}
if filter:
filter_dict = filter.model_dump(exclude_none=True)
if filter_dict: # Only add filter if it's not empty
payload["filter"] = filter_dict
try:
print(f"FINAL QUERY: {payload}")
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
raw_data = response.json()['data']
clean_data = clean_attio_data(raw_data)
return clean_data
except requests.exceptions.RequestException as e:
print(f"Error fetching deals: {e}")
print(f"Response content: {response.text if response else 'No response'}")
return []
This tool fetches deals from Attio based on the provided filters and sorts. It's used by the AI to find relevant deals based on the user's query.
Fetching Matching Deals
The DealSearcher agent uses the ListDealsTool to search for deals based on the user's query. Here's a snippet of the task that uses this agent:
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
query_deals_task = Task(
description=dedent(f"""
Using the filter (if provided) and sorts from the previous task, search for relevant deals using the ListDealsTool.
The previous task output is a JSON object with 'sorts' key and optionally 'filter' key.
Use this exact structure when calling the ListDealsTool:
Action: List Deals
Action Input: {{
"sorts": <insert sorts from previous task>,
"limit": 5
}}
If a filter was provided by the previous task, include it in the Action Input like this:
Action Input: {{
"filter": <insert filter from previous task>,
"sorts": <insert sorts from previous task>,
"limit": 5
}}
If no filter was provided, omit the 'filter' key entirely from the Action Input.
Do not modify the filter or sorts. Use them exactly as they are provided by the previous task.
If no deals are found initially, report this information accurately.
Return the list of matching deals or an explanation if no deals were found.
Original query: {query}
"""),
agent=DealSearcher,
context=[understand_query_task],
expected_output=
"A list of deal objects or an explanation if no deals were found.")
This task instructs the AI on how to use the ListDealsTool to find relevant deals based on the user's query.
Summarizing Results
The final step involves summarizing the found deal data. This is handled by the MessageSummarizer agent and its associated task:
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
create_summarization_task = Task(
description=dedent(f"""
Summarize the information found in the earlier deal research and
output a 1-2 sentence summary of the findings.
If you need to aggregate the deals to answer the query: {query}
Then use the AggregateDealDataTool to process the results.
Only use the aggregator tools if an aggregation is requested in the query
and you don't already have the aggregated data.
If you already have aggregated data or a summary from previous steps,
use that information directly without recalculating.
Do not invent or create data. Only use what is provided by earlier tasks with data.
"""),
agent=MessageSummarizer,
expected_output=
"A 1-2 sentence summary of the findings based on the deal data and user query."
)
This task ensures that the bot provides a concise, relevant summary based on the deals found and the user's original query.
Running Your Bot #
To run your bot:
- Make sure all required secrets are set in the Replit Secrets tab.
- Click the "Run" button in Replit.
- Your bot should now be active in your Slack workspace. You'll see a message "⚡️ Bolt app is running!" in the Console.
To interact with your bot, mention it in a channel where it's been invited, followed by your query about Attio deals.
Add your bot to a channel by heading to Integrations in the top-right corner. Click on Add apps. Search for your new Slackbot and add it to the channel.
Deploying Your Bot #
In order to keep your bot running 24/7 and receive requests whenever someone mentions it in Slack, you'll need to deploy it on a hosted server.
Open a new tab in the Workspace and search for “Deployments” or open the control console by typing ⌘ + K (or Ctrl + K) and type "deploy". You should find a screen like this.

For bots like this that need always need to be up listening to requests, we recommend using a Reserved VM. On the next screen, click Approve and configure build settings most internal bots work fine with the default machine settings but if you need more power later, you can always come back and change these settings later. You can monitor your usage and billing at any time at: replit.com/usage.
On the next screen, you’ll be able to set your primary domain and edit the Secrets that will be in your production deployment. Usually, we keep these settings as they are.
Finally, click Deploy and watch your bot go live!
What's Next #
To further improve your Attio AI Slackbot, consider:
- Enhancing the ListDealsTool for better accuracy and performance. This could involve explicitly prompting the agent for more filter and sorting combinations.
- Adding more tools and tasks to expand the bot's capabilities. For example, you could create tools to:
- Update deal information
- Create new deals
- Fetch and analyze Notes
- Adding conversational context to allow for follow-up questions and more natural interactions.
If you’d like to bring this project and similar templates into your team, set some time here with the Replit team for a quick demo of Replit Teams.
Happy coding!