Configuration

Option 1: Using the HumanLayer Slack App

The quickest way to get started with Slack integration:

  1. Head to the HumanLayer dashboard
  2. Navigate to “Integrations”
  3. Click “HumanLayer App” under the Slack section
  4. Follow the Slack Approval Workflow
  5. Congrats - your HumanLayer agents will now contact you in Slack for approvals

Option 2: Using Your Own Slack App

For teams that need more customization, you can use your own Slack app. This option is ideal for:

  • Customizing the bot’s display name, icon, and branding
  • Using a consistent bot identity across multiple integrations
  • Managing app distribution and permissions at an organizational level
  • Custom approval UI with your brand’s look and feel
  • Enterprise policy compliance
  1. Create a Slack App - Create a new Slack app in your workspace with the following manifest:
{
  "display_information": {
    "name": "My App",
    "description": "My App",
    "background_color": "#000000"
  },
  "features": {
    "bot_user": {
      "display_name": "My App",
      "always_online": false
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "users.profile:read",
        "users:read",
        "commands",
        "channels:history",
        "channels:read",
        "chat:write",
        "groups:history",
        "groups:write",
        "im:history",
        "im:read",
        "im:write"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://api.humanlayer.dev/humanlayer/v1/slack/events",
      "bot_events": [
        "message.channels",
        "message.groups",
        "message.im",
        "app_mention"
      ]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://api.humanlayer.dev/humanlayer/v1/slack/interactions"
    },
    "org_deploy_enabled": false,
    "socket_mode_enabled": false,
    "token_rotation_enabled": false
  }
}
  1. Configure Your App in HumanLayer:

    • In the HumanLayer dashboard, navigate to your project’s settings
    • Navigate to “Integrations”. Select “Use Your Own” under the Slack section.
    • Enter your Slack app’s Signing Secret and App ID
    • Save the configuration
  2. Get Your OAuth Token:

    • For testing, you can use the Bot User OAuth Token from your Slack app settings
    • For production, implement a proper OAuth flow following Slack’s documentation
  3. Use Your Bot Token with HumanLayer SDK:

    • When initializing HumanLayer, provide your bot token in the contact channel configuration:
import os
from humanlayer import HumanLayer, ContactChannel, SlackContactChannel, FunctionCallSpec

bot_token = "...YOUR BOT TOKEN"

hl = HumanLayer(
api_key=os.getenv("HUMANLAYER_API_KEY"),
verbose=True,
contact_channel=ContactChannel(
slack=SlackContactChannel(
bot_token=bot_token,
channel_or_user_id="", # leave blank to dm whoever installed the app
experimental_slack_blocks=True,
)
),
)

hl.fetch_approval(
spec=FunctionCallSpec(
fn="add",
kwargs={"x": 2, "y": 5},
)
)

For a complete example that makes use of a custom Slack app, see 06-custom_bot_token.py in our examples directory. Be sure you have a Slack application setup before attempting to run the script.

Troubleshooting

If you encounter issues with your custom Slack app integration:

  1. Verify Scopes - Ensure your app has all the required scopes listed in the manifest
  2. Check Request URLs - The event subscription and interactivity URLs must point to the HumanLayer API
  3. Verify Signing Secret - Double-check the signing secret entered in the HumanLayer dashboard
  4. Update/Reauthorize Slack Apps - If you’re updating an existing Slack app and have added new scopes, you’ll need to reauthorize the app via the OAuth flow you’ve built. Be sure to take a look at the embedded markup Slack provides in the “Manage Distribution” section of your app’s settings as these links and markup can change once you’ve updated scopes.

Customizing Channels

The Slack contact channel allows agents to send messages and collect responses through Slack channels or direct messages. Configure a Slack channel using the SlackContactChannel model:

from humanlayer import ContactChannel, SlackContactChannel

dm_with_ceo = ContactChannel(
    slack=SlackContactChannel(
        channel_or_user_id="U123456",  # Must be an ID like C123456 or U123456, not #channel or @user
        context_about_channel_or_user="a DM with the CEO",  # Optional context for the LLM
        experimental_slack_blocks=True,  # Optional - enables rich message formatting
        allowed_responder_ids=["U123456"],  # Optional - restrict who can respond
    )
)

hl = HumanLayer(contact_channel=dm_with_ceo)

Allowed Responders

You can restrict which Slack users are allowed to respond to a message using allowed_responder_ids:

# Only allow specific users to approve add operations
add_approver_channel = ContactChannel(
    slack=SlackContactChannel(
        channel_or_user_id="C123456",
        context_about_channel_or_user="the channel for add operations",
        allowed_responder_ids=["U123456"],  # Only this user can approve
    )
)

@hl.require_approval(contact_channel=add_approver_channel)
def add(a: float, b: float) -> float:
    """Add two numbers"""
    return a + b

The allowed_responder_ids must be Slack user IDs (starting with U). Messages from other users will be ignored.

See 01-math-example-allowed-repliers.py for a complete example.

Thread Messages

You can specify a thread to post messages in using the thread_ts parameter:

# Post in a specific Slack thread
threaded_channel = ContactChannel(
    slack=SlackContactChannel(
        channel_or_user_id="C123456",
        thread_ts="1234567890.123456",  # Timestamp of the parent message
    )
)

The thread_ts parameter accepts a Slack message timestamp (e.g. “1234567890.123456”) which identifies the parent message of the thread. When specified, all messages will be posted as replies in that thread instead of as new messages in the channel.

This is useful for organizing related approvals or keeping discussions contained within specific threads.

Channel/User ID

The channel_or_user_id must be a Slack ID:

  • Channel IDs start with C (e.g. C123456)
  • User IDs start with U (e.g. U123456)
  • Do not use channel names (#general) or usernames (@user)

You can get a channel ID in slack by right-clicking the channel, going to “Channel Details”, and copying the ID at the bottom of the modal.

You can also override the contact channel at the per-request level:

hl = HumanLayer()

@hl.require_approva(contact_channel=dm_with_ceo)
def send_email():
    ...

Or in one or more human-as tool instances

tools = [
  hl.human_as_tool(contact_channel=channel_with_sre_team),
  hl.human_as_tool(contact_channel=dm_with_ceo),
]

Context

The optional context_about_channel_or_user field helps the LLM understand who it’s talking to:

# Good context examples
"a DM with the CEO"
"the channel with the SRE team"
"a private channel for approvals"

Usage

Use the Slack channel with either core feature:

# With require_approval
@hl.require_approval(contact_channel=dm_with_ceo)
def send_email(to: str, subject: str, body: str) -> str:
    """Send an email to a customer"""
    return f"Email sent to {to}"

# With human_as_tool
tools = [
    langchain_tools.StructuredTool.from_function(
        hl.human_as_tool(
            contact_channel=dm_with_ceo,
        )
    ),
]

Next Steps