Serve a Support Team in Slack

Route each Slack request to a technical specialist or a documentation specialist that can search current workspace discussions.

team.py
"""
Serve a Support Team in Slack
=============================

Route each Slack request to a technical specialist or a documentation
specialist that can search current workspace discussions.

Prerequisites: SLACK_TOKEN, SLACK_SIGNING_SECRET, OPENAI_API_KEY
Run: .venvs/demo/bin/python cookbook/05_agent_os/17_slack/team.py
Try in Slack: Ask "How should I debug our API timeout, and has the team discussed it?"
Slack scopes: app_mentions:read, assistant:write, chat:write, im:history, search:read.public, search:read.files, search:read.users
"""

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS
from agno.os.interfaces.slack import Slack
from agno.team import Team
from agno.tools.slack import SlackTools
from agno.tools.websearch import WebSearchTools

# ---------------------------------------------------------------------------
# Create Support Team Slack AgentOS
# ---------------------------------------------------------------------------

db = SqliteDb(
    id="slack-support-team-db",
    db_file="tmp/slack_support_team.db",
)

technical_specialist = Agent(
    id="slack-technical-specialist",
    name="Technical Specialist",
    role="Diagnose code, API, and infrastructure problems.",
    model=OpenAIResponses(id="gpt-5.5"),
    tools=[WebSearchTools()],
    instructions=[
        "Diagnose the likely cause before proposing changes.",
        "Use current primary documentation when external facts matter.",
    ],
    markdown=True,
)

documentation_specialist = Agent(
    id="slack-documentation-specialist",
    name="Documentation Specialist",
    role="Find relevant workspace discussions and explain existing guidance.",
    model=OpenAIResponses(id="gpt-5.5"),
    tools=[
        SlackTools(
            enable_send_message=False,
            enable_send_message_thread=False,
            enable_list_channels=False,
            enable_get_channel_history=False,
            enable_upload_file=False,
            enable_download_file=False,
            enable_search_workspace=True,
        )
    ],
    instructions=[
        "Search the Slack workspace for prior decisions and related incidents.",
        "Summarize what was decided and link the evidence returned by the tool.",
    ],
    markdown=True,
)

support_team = Team(
    id="slack-support-team",
    name="Slack Support Team",
    model=OpenAIResponses(id="gpt-5.5"),
    members=[technical_specialist, documentation_specialist],
    db=db,
    instructions=[
        "Delegate debugging to the Technical Specialist.",
        "Delegate questions about prior team context to the Documentation Specialist.",
        "Use both members when a request needs diagnosis and workspace history.",
        "Return one concise, actionable response.",
    ],
    add_history_to_context=True,
    num_history_runs=3,
    markdown=True,
)

agent_os = AgentOS(
    id="slack-team-os",
    description="AgentOS serving a specialist support Team through Slack.",
    teams=[support_team],
    interfaces=[Slack(team=support_team)],
)
app = agent_os.get_app()

# ---------------------------------------------------------------------------
# Run Support Team Slack AgentOS
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    agent_os.serve(app=app)

Workspace search limitation

Before running this example, change enable_search_workspace=True to enable_search_workspace=False in its SlackTools constructor and remove the instruction to use workspace search.

The current adapter reads event.assistant_thread.action_token; it drops a top-level event.action_token, as used in Slack's current agent example. A request with only the top-level token therefore cannot use search_workspace through this adapter.

These examples also persist tool results, including retrieved workspace data, in SQLite. Slack's Real-time Search data policy prohibits retaining data retrieved by that API. Enabling workspace search requires both compatible event-token handling and a verified storage design for the retrieved data. A single storage flag is not presented here as a complete fix.

In this team, the Documentation Specialist disables every other Slack tool. With workspace search disabled, it has no Slack retrieval tool; supply the relevant documentation in the conversation until that integration is repaired.

Run the Example

Set up your virtual environment

uv venv --python 3.12
source .venv/bin/activate

Prepare the Slack app

Follow Slack setup to create and install the app, obtain its bot token and signing secret, and configure its current agent experience. Add the bot scopes listed in this example's source docstring and reinstall after changing scopes. Subscribe to app_mention and message.im; configure interactivity for buttons and forms.

Install ngrok and run ngrok http 7777 in another terminal. Keep the tunnel running. After starting this example's server, use the callback paths listed on this page under your public HTTPS URL and complete Slack's verification challenge. Configure each app separately for a multi-app example.

Streaming requires the corresponding Slack app capability. The current Agno adapter initializes suggested prompts on the legacy assistant_thread_started event; the setup guide explains the new-app limitation. Keep only one standalone example on port 7777 at a time.

Install dependencies

uv pip install -U "agno[os,slack]" ddgs openai

Export environment variables

export OPENAI_API_KEY="your_openai_api_key_here"
export SLACK_SIGNING_SECRET="your_slack_signing_secret_here"
export SLACK_TOKEN="your_slack_token_here"

Run the example

Save the code above as team.py, then run:

python team.py

Connect Slack to the running server

Keep Python and ngrok running. In each app's Slack settings, prepend your public HTTPS origin to these paths:

AppEvent subscriptionsInteractivity
Slack app/slack/events/slack/interactions

Complete URL verification, then send a DM or invite the app to a channel and @mention it. Ordinary channel replies require an @mention with the default configuration.

Full source: cookbook/05_agent_os/17_slack/team.py