HomeBuild toolsCreate a tool with auth

Adding user authorization to your tools

In this guide, you’ll learn how to add user authorization to your custom tools, using Arcade.

You’ll create a tool that sends a message on behalf of a user via Slack.

Prerequisites

pip install arcade-ai slack_sdk

Define your authorized tool

Create a new Python file, e.g., slack_tools.py, and import the necessary modules:

from typing import Annotated
 
from arcade.sdk import ToolContext, tool
from arcade.sdk.auth import Slack
from arcade.sdk.errors import RetryableToolError
from slack_sdk import WebClient

Now, define your tool using the @tool decorator and specify the required authorization, in this case, by using the built-in Slack auth provider:

@tool(
    requires_auth=Slack(
        scopes=[
            "chat:write",
            "im:write",
            "users.profile:read",
            "users:read",
        ],
    )
)
def send_dm_to_user(
    context: ToolContext,
    user_name: Annotated[str, "The Slack username of the person you want to message"],
    message: Annotated[str, "The message you want to send"],
):
    """Send a direct message to a user in Slack."""
    slack_client = WebClient(token=context.authorization.token)
 
    # Retrieve the user ID based on username
    user_list_response = slack_client.users_list()
    user_id = None
    for user in user_list_response["members"]:
        if user["name"].lower() == user_name.lower():
            user_id = user["id"]
            break
    if not user_id:
        raise RetryableToolError(
            "User not found",
            developer_message=f"User with username '{user_name}' not found."
        )
 
    # Open a conversation and send the message
    im_response = slack_client.conversations_open(users=[user_id])
    dm_channel_id = im_response["channel"]["id"]
    slack_client.chat_postMessage(channel=dm_channel_id, text=message)

Arcade offers a number of built-in auth providers, including Slack, Google, and GitHub. You can also require authorization with a custom auth provider, using the OAuth2 class, a subclass of the ToolAuthorization class:

@tool(
    requires_auth=OAuth2(
        id="your-oauth-provider-id",
        scopes=["scope1", "scope2"],
    )
)

The OAuth2 class requires an id parameter to identify the auth provider in the Arcade Engine. For built-in providers like Slack, you can skip the id - the Arcade Engine will find the right provider using your credentials. While you can specify an id for built-in providers, only do this for private tools that won’t be shared.

Register your tool

As before, you need to register your tool in a ToolCatalog:

from arcade.sdk import ToolCatalog
from slack_tools import send_dm_to_user
 
catalog = ToolCatalog()
catalog.add_tool(send_dm_to_user)

Use your authorized tool with Arcade

Now you can use your custom authorized tool with Arcade in your application.

Here’s an example of how to use your tool:

from arcadepy import Arcade
from catalog import catalog
 
client = Arcade()  # Automatically finds the `ARCADE_API_KEY` env variable
 
user_id = "[email protected]"
 
# Use the tool in a chat completion
response = client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "Send a message to johndoe on Slack saying 'Hello!'",
        }
    ],
    model="gpt-4o",
    tools=list(catalog.tools.keys()),
    tool_choice="auto",
    user=user_id,
)
 
print(response.choices[0].message.content)

Handle authorization

Since your tool requires authorization, the first time you use it, the user (identified by user_id) needs to authorize access.

Arcade handles the authorization flow, prompting the user to visit a URL to grant permissions.

Your application should guide the user through this process.

How it works

By specifying the requires_auth parameter in the @tool decorator, you indicate that the tool needs user authorization.

Arcade manages the OAuth flow, and provides the token in context.authorization.token when the tool is executed. Arcade also remembers the user’s authorization tokens, so they won’t have to go through the authorization process again until the auth expires or is revoked.

Next steps

Try adding more authorized tools, or explore how to handle different authorization providers and scopes.