Slack Integration

Human-in-the-loop approval workflows via Slack

Slack Integration

AgentSudo integrates with Slack to provide human-in-the-loop (HITL) approval workflows. When an agent attempts an action it doesn't have permission for, you can route the request to Slack for manual approval.

Features

  • Interactive Buttons - Approve or deny requests with one click
  • Slash Commands - /agentsudo approve <id>, /agentsudo deny <id>, /agentsudo pending
  • Thread Context - Full context about the agent, scope, and function
  • Timeout Handling - Auto-deny or raise exception on timeout
  • Audit Trail - All approvals logged with who approved and when

Quick Start

The easiest way to use Slack approvals is with AgentSudo Cloud:

from agentsudo import Agent, sudo
from agentsudo.slack import SlackApproval

slack = SlackApproval(
    cloud_api_key="as_...",  # Or set AGENTSUDO_API_KEY env var
    timeout=300,  # 5 minutes
)

@sudo(scope="delete:customer", on_deny=slack.request_approval)
def delete_customer(customer_id: str):
    # This will trigger a Slack approval if agent lacks scope
    ...

Then connect Slack in your AgentSudo Dashboard.

Option 2: Direct Slack Integration

For self-hosted setups, use a Slack Bot Token:

from agentsudo.slack import SlackApproval

slack = SlackApproval(
    bot_token="xoxb-...",  # Or set SLACK_BOT_TOKEN env var
    channel="#approvals",
    timeout=300,
)

Setup Guide

1. Create a Slack App

  1. Go to api.slack.com/apps
  2. Click Create New AppFrom scratch
  3. Name it "AgentSudo" and select your workspace

2. Configure Bot Permissions

Under OAuth & Permissions, add these Bot Token Scopes:

  • chat:write - Send messages
  • commands - Slash commands
  • incoming-webhook - Webhook messages (optional)

3. Enable Interactive Components

Under Interactivity & Shortcuts:

  1. Toggle Interactivity to On
  2. Set Request URL to: https://agentsudo.dev/api/slack/interact (Or your self-hosted endpoint)

4. Add Slash Command

Under Slash Commands, create:

  • Command: /agentsudo
  • Request URL: https://agentsudo.dev/api/slack/command
  • Description: Manage AgentSudo approval requests

5. Install to Workspace

  1. Go to Install App
  2. Click Install to Workspace
  3. Copy the Bot User OAuth Token (xoxb-...)

Usage

Basic Approval Flow

from agentsudo import Agent, sudo
from agentsudo.slack import SlackApproval

slack = SlackApproval(
    bot_token="xoxb-...",
    channel="#approvals",
    timeout=300,
    auto_deny_on_timeout=True,
)

@sudo(scope="refund:large", on_deny=slack.request_approval)
def issue_refund(order_id: str, amount: float):
    """Issue a refund - requires approval for agents without scope."""
    return process_refund(order_id, amount)

# Agent without refund scope
agent = Agent(name="SupportBot", scopes=["read:orders"])

with agent.start_session():
    # This triggers Slack approval
    issue_refund("order_123", 500.00)

Convenience Function

For quick setup:

from agentsudo import sudo
from agentsudo.slack import create_slack_approval

slack_approve = create_slack_approval(
    bot_token="xoxb-...",
    channel="#approvals",
)

@sudo(scope="deploy:production", on_deny=slack_approve)
def deploy(version: str):
    ...

Environment Variables

Instead of passing credentials directly:

export SLACK_BOT_TOKEN=xoxb-...
export SLACK_APPROVAL_CHANNEL=#approvals
# OR for AgentSudo Cloud:
export AGENTSUDO_API_KEY=as_...
slack = SlackApproval()  # Reads from env vars

Slash Commands

Once installed, users can use these commands:

CommandDescription
/agentsudo approve <id>Approve a pending request
/agentsudo deny <id>Deny a pending request
/agentsudo pendingList all pending requests
/agentsudo helpShow help message

Configuration Options

SlackApproval(
    # Credentials (pick one)
    webhook_url="https://hooks.slack.com/...",  # Notifications only
    bot_token="xoxb-...",                        # Interactive buttons
    cloud_api_key="as_...",                      # AgentSudo Cloud
    
    # Settings
    channel="#approvals",      # Channel for messages
    timeout=300,               # Seconds to wait (default: 5 min)
    poll_interval=2,           # Seconds between status checks
    auto_deny_on_timeout=True, # Deny on timeout (vs raise exception)
)

Approval Message

When an approval is requested, Slack users see:

🔐 AgentSudo Approval Request
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Agent:      SupportBot
Scope:      delete:customer
Function:   delete_customer
Request ID: a1b2c3d4

⏱️ Expires in 300 seconds

[✅ Approve]  [❌ Deny]

Error Handling

from agentsudo.slack import SlackApproval, SlackApprovalTimeout

slack = SlackApproval(
    bot_token="xoxb-...",
    timeout=60,
    auto_deny_on_timeout=False,  # Raise exception instead
)

@sudo(scope="critical:action", on_deny=slack.request_approval)
def critical_action():
    ...

try:
    critical_action()
except SlackApprovalTimeout:
    print("No response received - action not taken")
except PermissionDeniedError:
    print("Request was denied")

Self-Hosted Webhook

If you're not using AgentSudo Cloud, you need to handle Slack interactions:

# FastAPI example
from fastapi import FastAPI, Request
from agentsudo.slack import SlackApproval

app = FastAPI()
slack = SlackApproval(bot_token="xoxb-...")

@app.post("/slack/interact")
async def slack_interact(request: Request):
    form = await request.form()
    payload = json.loads(form["payload"])
    
    action = payload["actions"][0]
    approval_id = action["value"]
    approved = action["action_id"] == "approve"
    user = payload["user"]["username"]
    
    slack.handle_interaction(approval_id, approved, user)
    
    return {"ok": True}

Best Practices

  1. Set appropriate timeouts - 5 minutes is good for most cases
  2. Use descriptive scopes - delete:customer is clearer than delete
  3. Channel selection - Use a dedicated #approvals channel
  4. Audit everything - Enable cloud telemetry for full audit trail
  5. Fallback handling - Always handle timeout/denial gracefully

Next Steps