Skip to content

Commit 2a43e89

Browse files
m1kl0shmdrxy
andauthored
feat(agent_toolkits): Make WebClient injectable for Slack toolkit (#145)
This PR enables injecting a [`WebClient`](https://tools.slack.dev/python-slack-sdk/api-docs/slack_sdk/web/client.html) instance into all tools within the Slack toolkit. This simplifies usage for agents that need to work with [user tokens](https://api.slack.com/concepts/token-types#user). --------- Co-authored-by: Mason Daugherty <[email protected]>
1 parent b8ba731 commit 2a43e89

File tree

2 files changed

+72
-4
lines changed

2 files changed

+72
-4
lines changed

libs/community/langchain_community/agent_toolkits/slack/toolkit.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,14 @@ class SlackToolkit(BaseToolkit):
4646
4747
from langchain_community.agent_toolkits import SlackToolkit
4848
49+
# Using environment variables (default)
4950
toolkit = SlackToolkit()
5051
52+
# Or with an existing WebClient instance
53+
from slack_sdk import WebClient
54+
client = WebClient(token="your-user-token")
55+
toolkit = SlackToolkit(client=client)
56+
5157
Tools:
5258
.. code-block:: python
5359
@@ -105,8 +111,8 @@ class SlackToolkit(BaseToolkit):
105111
def get_tools(self) -> List[BaseTool]:
106112
"""Get the tools in the toolkit."""
107113
return [
108-
SlackGetChannel(),
109-
SlackGetMessage(),
110-
SlackScheduleMessage(),
111-
SlackSendMessage(),
114+
SlackGetChannel(client=self.client),
115+
SlackGetMessage(client=self.client),
116+
SlackScheduleMessage(client=self.client),
117+
SlackSendMessage(client=self.client),
112118
]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import sys
2+
from unittest.mock import MagicMock
3+
4+
import pytest
5+
6+
# Mock slack_sdk module and WebClient class.
7+
mock_slack_sdk = MagicMock()
8+
mock_webclient_class = MagicMock()
9+
mock_slack_sdk.WebClient = mock_webclient_class
10+
sys.modules["slack_sdk"] = mock_slack_sdk
11+
12+
# We need to import the toolkit after patching sys.modules.
13+
# ruff: noqa: E402
14+
from langchain_community.agent_toolkits.slack.toolkit import SlackToolkit
15+
from langchain_community.tools.slack.base import SlackBaseTool
16+
17+
18+
@pytest.fixture
19+
def mock_webclient() -> MagicMock:
20+
mock_client = MagicMock()
21+
mock_client.api_test.return_value = {"ok": True}
22+
return mock_client
23+
24+
25+
def test_slack_toolkit_default_instantiation() -> None:
26+
"""Test SlackToolkit can be instantiated with default settings."""
27+
toolkit = SlackToolkit()
28+
assert toolkit is not None
29+
30+
tools = toolkit.get_tools()
31+
32+
assert len(tools) == 4
33+
for tool in tools:
34+
assert isinstance(tool, SlackBaseTool)
35+
assert tool.client == toolkit.client
36+
37+
38+
def test_slack_toolkit_get_tools_provided_client(mock_webclient: MagicMock) -> None:
39+
"""Test that get_tools() creates tools with the provided client."""
40+
toolkit = SlackToolkit(client=mock_webclient)
41+
42+
tools = toolkit.get_tools()
43+
44+
assert len(tools) == 4
45+
for tool in tools:
46+
assert isinstance(tool, SlackBaseTool)
47+
assert tool.client == mock_webclient
48+
49+
50+
def test_slack_toolkit_provided_client_reuse(mock_webclient: MagicMock) -> None:
51+
"""Test that provided client instance is reused across multiple get_tools()
52+
calls."""
53+
toolkit = SlackToolkit(client=mock_webclient)
54+
tools1 = toolkit.get_tools()
55+
tools2 = toolkit.get_tools()
56+
57+
for i in range(len(tools1)):
58+
tool1 = tools1[i]
59+
tool2 = tools2[i]
60+
assert isinstance(tool1, SlackBaseTool)
61+
assert isinstance(tool2, SlackBaseTool)
62+
assert tool1.client == tool2.client == mock_webclient

0 commit comments

Comments
 (0)