Back to Promptfoo

Slack Provider

site/docs/providers/slack.md

0.121.914.5 KB
Original Source

Slack Provider

The Slack provider enables human-in-the-loop evaluations by sending prompts to Slack channels or users and collecting responses. This is useful for:

  • Collecting human feedback on AI outputs
  • Comparing human responses with AI responses
  • Building golden datasets from expert feedback
  • Running evaluations with domain experts

Prerequisites

Install Dependencies

The Slack provider requires the @slack/web-api package to be installed separately:

bash
npm install @slack/web-api

:::note This is an optional dependency and only needs to be installed if you want to use the Slack provider. :::

Slack App Setup

  1. Create a Slack App

    • Go to api.slack.com/apps
    • Click "Create New App" → "From scratch"
    • Give your app a name and select your workspace
  2. Configure Bot Token Scopes

    • Navigate to "OAuth & Permissions" in your app settings
    • Under "Scopes" → "Bot Token Scopes", add these REQUIRED scopes:
      • chat:write - to send messages
      • channels:history - to read public channel messages
      • groups:history - to read private channel messages
      • im:history - to read direct messages
      • channels:read - to access public channel information
      • groups:read - to access private channel information
      • im:read - to access direct message information

    Note: All scopes are required for the provider to work properly across different channel types.

  3. Install App to Workspace

    • Go to "Install App" in your app settings
    • Click "Install to Workspace"
    • Copy the "Bot User OAuth Token" (starts with xoxb-)
  4. Invite Bot to Channel

    • In Slack, go to the channel where you want to use the bot
    • Type /invite @YourBotName

Configuration

Environment Variables

bash
export SLACK_BOT_TOKEN="xoxb-your-bot-token"

Basic Configuration

yaml
providers:
  - id: slack
    config:
      channel: 'C0123456789' # Your channel ID

Provider Formats

The Slack provider supports multiple formats:

yaml
# Basic format with channel in config
providers:
  - id: slack  # Uses SLACK_BOT_TOKEN env var
    config:
      # token: "{{ env.SLACK_BOT_TOKEN }}"  # optional, auto-detected
      channel: "C0123456789"

# Short format - channel ID directly in provider string
providers:
  - slack:C0123456789

# Explicit channel format
providers:
  - slack:channel:C0123456789

# Direct message to a user
providers:
  - slack:user:U0123456789

Configuration Options

OptionTypeRequiredDefaultDescription
tokenstringYes*SLACK_BOT_TOKEN env varSlack Bot User OAuth Token
channelstringYes-Channel ID (C...) or User ID (U...)
responseStrategystringNo'first'How to collect responses: 'first', 'user', or 'timeout'
waitForUserstringNo-User ID to wait for (when using 'user' strategy)
timeoutnumberNo60000Timeout in milliseconds
includeThreadbooleanNofalseInclude thread timestamp in output metadata
formatMessagefunctionNo-Custom message formatting function
threadTsstringNo-Thread timestamp to reply in

*Token is required either in config or as environment variable

Response Strategies

First Response (Default)

Captures the first non-bot message after the prompt:

yaml
providers:
  - id: slack
    config:
      channel: 'C0123456789'
      responseStrategy: 'first'

Specific User

Waits for a response from a specific user:

yaml
providers:
  - id: slack
    config:
      channel: 'C0123456789'
      responseStrategy: 'user'
      waitForUser: 'U9876543210'

Timeout Collection

Collects all responses until timeout:

yaml
providers:
  - id: slack
    config:
      channel: 'C0123456789'
      responseStrategy: 'timeout'
      timeout: 300000 # 5 minutes

Finding Channel and User IDs

Channel IDs

  1. In Slack, click on the channel name in the header
  2. Click "About" tab
  3. At the bottom, you'll see the Channel ID (starts with C)

User IDs

  1. Click on a user's profile
  2. Click the "..." menu
  3. Select "Copy member ID" (starts with U)

Alternative Method

  1. Right-click on a channel/user in the sidebar
  2. Select "Copy link"
  3. The ID is at the end of the URL

Channel ID Formats

  • C... - Public channels
  • G... - Private channels/groups
  • D... - Direct messages
  • W... - Shared/Connect channels

Examples

Basic Human Feedback Collection

yaml
description: Collect human feedback on AI responses

providers:
  - id: openai:gpt-5
  - id: slack:C0123456789
    config:
      timeout: 300000 # 5 minutes

prompts:
  - 'Explain {{topic}} in simple terms'

tests:
  - vars:
      topic: 'quantum computing'
  - vars:
      topic: 'machine learning'
  - vars:
      topic: 'blockchain technology'
# Run with: promptfoo eval -j 1

Expert Review with Specific User

yaml
description: Get expert feedback from specific team member

providers:
  - id: slack
    config:
      channel: 'C0123456789'
      responseStrategy: 'user'
      waitForUser: 'U9876543210' # Expert's user ID
      timeout: 600000 # 10 minutes

prompts:
  - file://prompts/technical-review.txt

tests:
  - vars:
      code: |
        def factorial(n):
          if n == 0:
            return 1
          return n * factorial(n-1)

Thread-based Conversations

yaml
description: Continue conversation in thread

providers:
  - id: slack
    config:
      channel: 'C0123456789'
      threadTs: '1234567890.123456' # Existing thread
      includeThread: true

prompts:
  - 'Follow-up question: {{question}}'

Custom Message Formatting

javascript
// promptfooconfig.js
module.exports = {
  providers: [
    {
      id: 'slack',
      config: {
        channel: 'C0123456789',
        formatMessage: (prompt) => {
          return `🤖 *AI Evaluation Request*\n\n${prompt}\n\n_Please provide your feedback_`;
        },
      },
    },
  ],
};

Best Practices

  1. Concurrency: Run Slack evaluations with -j 1 to ensure messages are sent sequentially

    bash
    promptfoo eval -j 1
    
  2. Timeouts: Set appropriate timeouts based on expected response time

    • Quick feedback: 60-120 seconds
    • Detailed review: 5-10 minutes
    • Async collection: 30+ minutes
  3. Channel Selection:

    • Use dedicated evaluation channels to avoid spam
    • Consider private channels for sensitive evaluations
    • Use DMs for individual expert feedback
  4. Message Formatting:

    • Use clear, structured prompts
    • Include context and instructions
    • Use Slack's markdown for better readability
  5. Rate Limits: Be aware of Slack's rate limits

    • Web API: ~1 request per second per method
    • Consider adding delays for bulk evaluations

Testing Other Slack Bots

The Slack provider is excellent for testing other Slack bots in their native environment. This allows you to:

  • Evaluate bot responses to various prompts
  • Compare different bot implementations
  • Perform regression testing
  • Test bot behavior under different scenarios

Setup for Bot Testing

  1. Invite both bots to a test channel:

    /invite @your-bot-to-test
    /invite @provider
    
  2. Configure the provider to mention the target bot:

    yaml
    providers:
      - id: slack
        config:
          channel: C123456789
          timeout: 10000
          responseStrategy: first
          # Optional: format messages to mention the bot
          messageFormatter: |
            @your-bot-to-test {{prompt}}
    
  3. Filter responses to only capture the target bot:

    yaml
    providers:
      - id: slack
        config:
          channel: C123456789
          timeout: 10000
          responseStrategy: user
          userId: U_YOUR_BOT_ID # The bot's user ID
    

Example: Testing a Customer Support Bot

yaml
description: Test our customer support bot

providers:
  - id: slack
    label: support-bot-test
    config:
      channel: C_TEST_CHANNEL
      timeout: 15000
      responseStrategy: user
      userId: U_SUPPORT_BOT_ID
      messageFormatter: |
        <@U_SUPPORT_BOT_ID> {{prompt}}

prompts:
  - 'How do I reset my password?'
  - 'What are your business hours?'
  - 'I need to speak to a human'
  - "My order hasn't arrived yet, order #12345"

tests:
  - vars:
      expected_intent: password_reset
    assert:
      - type: contains
        value: 'reset'
      - type: contains
        value: 'password'

  - vars:
      expected_intent: business_hours
    assert:
      - type: contains-any
        value: ['hours', 'open', 'closed', 'Monday', 'schedule']

  - vars:
      expected_intent: human_handoff
    assert:
      - type: contains-any
        value: ['agent', 'representative', 'transfer', 'human']

  - vars:
      expected_intent: order_status
    assert:
      - type: contains
        value: '12345'
      - type: javascript
        value: |
          // Check if bot asked for more info or provided status
          return output.includes('track') || output.includes('status') || output.includes('delivery');

Advanced Bot Testing Patterns

1. Multi-turn Conversations

Test conversation flows by chaining prompts:

yaml
prompts:
  - "Hi, I'd like to order a pizza"
  - 'Yes, I want a large pepperoni'
  - 'My address is 123 Main St'

2. Error Handling

Test how the bot handles invalid inputs:

yaml
prompts:
  - 'HELP ME NOW!!!!!!'
  - 'asdfghjkl'
  - "' OR 1=1 --"
  - ''

3. Load Testing

Use multiple parallel evaluations to test bot performance:

bash
promptfoo eval -c bot-test-config.yaml -j 10

4. A/B Testing Different Bots

Compare multiple bot implementations:

yaml
providers:
  - id: slack
    label: bot-v1
    config:
      channel: C_CHANNEL_V1
      userId: U_BOT_V1

  - id: slack
    label: bot-v2
    config:
      channel: C_CHANNEL_V2
      userId: U_BOT_V2

prompts:
  - "What's your return policy?"

assert:
  - type: llm-rubric
    value: 'Response should be helpful, accurate, and mention the 30-day return window'

Best Practices for Bot Testing

  1. Use dedicated test channels to avoid disrupting production
  2. Set appropriate timeouts - bots may take longer to respond than humans
  3. Test edge cases including malformed inputs and prompt injection attempts
  4. Monitor rate limits when running many tests
  5. Use assertions to verify both content and format of responses
  6. Test at different times to ensure consistent performance

Finding Bot User IDs

To find a bot's user ID:

javascript
// Run this in your test channel
const { WebClient } = require('@slack/web-api');
const client = new WebClient(process.env.SLACK_BOT_TOKEN);

async function findBotId() {
  const members = await client.conversations.members({
    channel: 'C_YOUR_CHANNEL',
  });

  for (const userId of members.members) {
    const user = await client.users.info({ user: userId });
    if (user.user.is_bot) {
      console.log(`Bot: ${user.user.name} - ID: ${userId}`);
    }
  }
}

Troubleshooting

Bot not responding

  • Ensure bot is invited to the channel
  • Check bot has required permissions
  • Verify token is valid

Timeout errors

  • Increase timeout value
  • Check if users are active in channel
  • Consider using different response strategy

Missing messages

  • Ensure bot has channels:history permission
  • Check if messages are in threads
  • Verify channel ID is correct

Security Considerations

  • Store tokens as environment variables, not in config files
  • Use private channels for sensitive data
  • Regularly rotate bot tokens
  • Limit bot permissions to minimum required
  • Remove bot from channels when not in use

Complete Example

yaml
# Human evaluation of customer service responses
description: Compare AI and human customer service responses

providers:
  - id: openai:gpt-5
    config:
      temperature: 0.7

  - id: anthropic:messages:claude-sonnet-4-5-20250929

  - id: slack:C0123456789
    config:
      responseStrategy: 'first'
      timeout: 180000 # 3 minutes
      formatMessage: (prompt) =>
        `📋 *Customer Service Evaluation*\n\n${prompt}\n\n_How would you respond to this customer?_`

prompts:
  - |
    Customer message: "{{message}}"

    Please provide a helpful and empathetic response.

tests:
  - vars:
      message: "I've been waiting for my order for 2 weeks and no one is responding to my emails!"
    assert:
      - type: llm-rubric
        value: Response acknowledges delay and provides concrete next steps

  - vars:
      message: 'The product I received is damaged and I need a replacement'
    assert:
      - type: llm-rubric
        value: Response offers immediate solution and apologizes for inconvenience

  - vars:
      message: 'How do I upgrade my subscription plan?'
    assert:
      - type: contains
        value: upgrade
# Run evaluation
# promptfoo eval -j 1 --no-progress-bar

Testing Your Setup

Quick Test

  1. Create a test channel in Slack

  2. Invite your bot to the channel: /invite @YourBotName

  3. Create a simple test config:

    yaml
    providers:
      - id: slack:YOUR_CHANNEL_ID
        config:
          timeout: 30000
    
    prompts:
      - "Test message - please reply with 'success'"
    
    tests:
      - assert:
          - type: contains
            value: success
    
  4. Run: npx promptfoo eval -j 1

  5. Reply in Slack within 30 seconds

Common Issues

  • Bot not in channel: Always invite the bot first with /invite @YourBotName
  • No response captured: Check the bot has all required scopes
  • Rate limits: The provider polls every 1 second. For non-Marketplace apps with strict rate limits, consider increasing timeouts and using longer polling intervals

See Also