Skip to content

Commit

Permalink
Slack tool (#821)
Browse files Browse the repository at this point in the history
* TLK-1725 - Slack tool initial commit

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool lint

* TLK-1725 - Slack tool pyright

* TLK-1725 - Slack tool pyright

* TLK-1725 - Slack tool pyright

* TLK-1725 - Slack tool pyright

* TLK-1725 - Slack tool - pyright

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool small improvements

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool review fixes

* TLK-1725 - Slack tool review fixes

* TLK-1725 - Slack tool prettier

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool

* TLK-1725 - Slack tool
  • Loading branch information
EugeneLightsOn authored Nov 1, 2024
1 parent 642f2ad commit 404f286
Show file tree
Hide file tree
Showing 26 changed files with 715 additions and 45 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Toolkit is a deployable all-in-one RAG application that enables users to quickly
- [How to add tools](/docs/custom_tool_guides/tool_guide.md)
- [How to add auth to your tools](/docs/custom_tool_guides/tool_auth_guide.md)
- [How to setup Google Drive](/docs/custom_tool_guides/google_drive.md)
- [How to setup Slack Tool](/docs/custom_tool_guides/slack.md)
- [How to setup Google Text-to-Speech](/docs/text_to_speech.md)
- [How to add authentication](/docs/auth_guide.md)
- [How to deploy toolkit services](/docs/service_deployments.md)
Expand Down
131 changes: 131 additions & 0 deletions docs/custom_tool_guides/slack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Slack Tool Setup

To set up the Slack tool you will need a Slack application. Follow the steps below to set it up:

## 1. Create a Slack App

Head to the [Slack API](https://api.slack.com/apps) and create a new app.
After creating the app, you will see the `App Credentials` section. Copy the `Client ID` and `Client Secret` values.
That will be used for the environment variables specified above.

## 2. Set up OAuth & Permissions
OAuth flow is required to authenticate users with Slack.
To enable it please set the following redirect URL to your app's settings:
```bash
https://<your_backend_url>/v1/tool/auth
```
Please note that for the local development you will need to enable HTTPS.
See the [Setup HTTPS for Local Development](#5-setup-https-for-local-development) section for more details.
If you are using a local https setup, redirect url should be
```
https://localhost:8000/v1/tool/auth
```
Also, you can set up a proxy, such as [ngrok](https://ngrok.com/docs/getting-started/), to expose your local server to the internet.

The Slack tool uses User Token Scopes to access the user's Slack workspace.
The required and the default permission scope is `search:read`.
Set it in the `OAuth & Permissions` section of your Slack app settings.

To work with the Slack Tool Advanced token security via token rotation is required.
To enable it, go to the `OAuth & Permissions` section of your Slack app settings and click 'Opt in' button in the 'Advanced token security via token rotation' section.

More information about the OAuth flow can be found [here](https://api.slack.com/authentication/oauth-v2).

## 3. Set Up Environment Variables

Then set the following environment variables. You can either set the below values in your `secrets.yaml` file:
```bash
slack:
client_id: <your_client_id from step 1>
client_secret: <your_client_secret from step 1>
```
or update your `.env` configuration to contain:
```bash
SLACK_CLIENT_ID=<your_client_id from step 1>
SLACK_CLIENT_SECRET=<your_client_secret from step 1>
```

## 4. Enable the Slack Tool in the Frontend

To enable the Slack tool in the frontend, you will need to modify the `src/community/config/tools.py` file. Add the `TOOL_SLACK_ID` to the `AGENT_SETTINGS_TOOLS` list.

```typescript
export const AGENT_SETTINGS_TOOLS = [
TOOL_HYBRID_WEB_SEARCH_ID,
TOOL_PYTHON_INTERPRETER_ID,
TOOL_WEB_SCRAPE_ID,
TOOL_SLACK_ID,
];
```

To enable the Slack tool in the frontend for Base Agent, you will need to modify the `src/community/config/tools.py` file. Remove the `TOOL_SLACK_ID` from the `BASE_AGENT_EXCLUDED_TOOLS` list.
By default, the Slack Tool is disabled for the Base Agent. Also if you need to exclude some tool from the Base Agent just add it to the `BASE_AGENT_EXCLUDED_TOOLS` list.
```typescript
export const BASE_AGENT_EXCLUDED_TOOLS = [];
```

## 5. Setup HTTPS for Local Development

To enable HTTPS for local development, the self-signed certificate needs to be generated.
Run the following command in the project root directory to generate the certificate and key:

```bash
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
```

Then, update the backend Docker configuration(src/backend/Dockerfile) to use the generated certificate.
Just change next lines in the Dockerfile:
```Dockerfile
COPY pyproject.toml poetry.lock cert.pem key.pem ./
```
and
```Dockerfile
CMD uvicorn backend.main:app --reload --host 0.0.0.0 --port ${PORT} --timeout-keep-alive 300 --ssl-keyfile /workspace/key.pem --ssl-certfile /workspace/cert.pem
```
Change NEXT_PUBLIC_API_HOSTNAME environment variable in the .env `https` protocol:
```bash
NEXT_PUBLIC_API_HOSTNAME=https://localhost:8000
```

or in the configurations.yaml file:

```yaml
auth:
backend_hostname: https://localhost:8000
```
To run the Frontend with HTTPS, update the `start` script in the `package.json` file:

```json
"scripts": {
"dev": "next dev --port 4000 --experimental-https",
..........
}
```

Add the following line to the 'docker-compose.yml' file to the frontend environment variables:

```yaml
NEXT_PUBLIC_API_HOSTNAME=https://localhost:8000
```

and change the API_HOSTNAME to

```yaml
API_HOSTNAME: https://localhost:8000
```
also change the src/interfaces/assistants_web/.env.development file env variables to use https.

## 6. Run the Backend and Frontend

run next command to start the backend and frontend:

```bash
make dev
```

## 7. Troubleshooting

If you encounter any issues with OAuth, please check the following [link](https://api.slack.com/authentication/oauth-v2#errors)
For example, if you see the invalid_team_for_non_distributed_app error,
please ensure the app is distributed or try logging in with the workspace owner's account.
37 changes: 21 additions & 16 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ llama-index = "^0.11.10"
llama-index-llms-cohere = "^0.3.0"
llama-index-embeddings-cohere = "^0.2.1"
google-cloud-texttospeech = "^2.18.0"
slack-sdk = "^3.33.1"

[tool.poetry.group.dev]
optional = true
Expand Down
3 changes: 3 additions & 0 deletions src/backend/config/configuration.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ tools:
- tavily_web_search
python_interpreter:
url: http://terrarium:8080
slack:
user_scopes:
- search:read
feature_flags:
# Experimental features
use_agents_view: false
Expand Down
3 changes: 3 additions & 0 deletions src/backend/config/secrets.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ tools:
google_web_search:
api_key:
cse_id:
slack:
client_id:
client_secret:
auth:
secret_key:
google_oauth:
Expand Down
23 changes: 22 additions & 1 deletion src/backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,24 @@ class GDriveSettings(BaseSettings, BaseModel):
)


class SlackSettings(BaseSettings, BaseModel):
model_config = SETTINGS_CONFIG
client_id: Optional[str] = Field(
default=None,
validation_alias=AliasChoices("SLACK_CLIENT_ID", "client_id"),
)
client_secret: Optional[str] = Field(
default=None,
validation_alias=AliasChoices("SLACK_CLIENT_SECRET", "client_secret"),
)
user_scopes: Optional[str] = Field(
default=None,
validation_alias=AliasChoices(
"SLACK_USER_SCOPES", "scopes"
),
)


class TavilyWebSearchSettings(BaseSettings, BaseModel):
model_config = SETTINGS_CONFIG
api_key: Optional[str] = Field(
Expand Down Expand Up @@ -195,10 +213,13 @@ class ToolSettings(BaseSettings, BaseModel):
brave_web_search: Optional[BraveWebSearchSettings] = Field(
default=BraveWebSearchSettings()
)

hybrid_web_search: Optional[HybridWebSearchSettings] = Field(
default=HybridWebSearchSettings()
)
slack: Optional[SlackSettings] = Field(
default=SlackSettings()
)



class DatabaseSettings(BaseSettings, BaseModel):
Expand Down
20 changes: 20 additions & 0 deletions src/backend/config/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
PythonInterpreter,
ReadFileTool,
SearchFileTool,
SlackAuth,
SlackTool,
TavilyWebSearch,
WebScrapeTool,
)
Expand Down Expand Up @@ -43,6 +45,7 @@ class ToolName(StrEnum):
Google_Web_Search = GoogleWebSearch.NAME
Brave_Web_Search = BraveWebSearch.NAME
Hybrid_Web_Search = HybridWebSearch.NAME
Slack = SlackTool.NAME


ALL_TOOLS = {
Expand Down Expand Up @@ -239,6 +242,23 @@ class ToolName(StrEnum):
category=Category.WebSearch,
description="Returns a list of relevant document snippets for a textual query retrieved from the internet using a mix of any existing Web Search tools.",
),
ToolName.Slack: ManagedTool(
display_name="Slack",
implementation=SlackTool,
parameter_definitions={
"query": {
"description": "Query to search slack.",
"type": "str",
"required": True,
}
},
is_visible=True,
is_available=SlackTool.is_available(),
auth_implementation=SlackAuth,
error_message="SlackTool not available, please enable it in the SlackTool class.",
category=Category.DataLoader,
description="Returns a list of relevant document snippets from slack.",
),
}


Expand Down
3 changes: 3 additions & 0 deletions src/backend/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from backend.tools.hybrid_search import HybridWebSearch
from backend.tools.lang_chain import LangChainVectorDBRetriever, LangChainWikiRetriever
from backend.tools.python_interpreter import PythonInterpreter
from backend.tools.slack import SlackAuth, SlackTool
from backend.tools.tavily_search import TavilyWebSearch
from backend.tools.web_scrape import WebScrapeTool

Expand All @@ -23,4 +24,6 @@
"BraveWebSearch",
"GoogleWebSearch",
"HybridWebSearch",
"SlackTool",
"SlackAuth"
]
4 changes: 2 additions & 2 deletions src/backend/tools/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def is_auth_required(self, session: DBSessionDep, user_id: str) -> bool:
return False

# Refresh failed, delete existing Auth
tool_auth_crud.delete_tool_auth(session, self.TOOL_ID, user_id)
tool_auth_crud.delete_tool_auth(session, user_id, self.TOOL_ID)
return True

# Check access_token is retrievable
Expand All @@ -100,7 +100,7 @@ def is_auth_required(self, session: DBSessionDep, user_id: str) -> bool:
auth.refresh_token
except Exception():
# Retrieval failed, delete existing Auth
tool_auth_crud.delete_tool_auth(session, self.TOOL_ID, user_id)
tool_auth_crud.delete_tool_auth(session, user_id, self.TOOL_ID)
return True

# ToolAuth retrieved and is not expired
Expand Down
Loading

0 comments on commit 404f286

Please sign in to comment.