Slack Search & Media Tools
Run SlackContextProvider with Gemini sub-agents, enabling search_messages and opt-in media tools for file download and upload.
Both the outer agent and Slack sub-agents use gemini-3.5-flash. The example exposes optional media tools, but its main prompt demonstrates text search; it does not download or upload a file.
The source comments describe a broader search surface than this CLI configures. search_messages is registered only with a user token; a bot-only run has channel-history tools. search_workspace requires an action token in run metadata from Slack’s assistant integration. A user token alone does not enable it.
"""
Slack Search & Media Tools
==========================
Demonstrates SlackContextProvider with:
- **search_messages** — Search using the legacy API (works with user
tokens `xoxp-`). Both bot and assisted read agents now have this
enabled alongside `search_workspace`.
- **enable_media_tools** — Opt-in file handling:
- `download_file` on read agents (fetch images/files for multimodal)
- `upload_file` on write agent (post generated content)
This example uses Gemini as the sub-agent model for Slack operations,
while the outer agent uses a different model. This pattern is useful
when you want faster/cheaper tool calls but stronger reasoning on top.
Requires:
GOOGLE_API_KEY
SLACK_BOT_TOKEN (xoxb-) — uses channel history, no search
Optional:
SLACK_USER_TOKEN (xoxp-) — enables search_messages API
With a bot token, search_messages returns `not_allowed_token_type` and
the agent falls back to get_channel_history. With a user token, both
search methods are available.
Usage:
python cookbook/12_context/06_slack_search_media.py
"""
from __future__ import annotations
import asyncio
from agno.agent import Agent
from agno.context.slack import SlackContextProvider
from agno.models.google import Gemini
slack = SlackContextProvider(
model=Gemini(id="gemini-3.5-flash"),
enable_media_tools=True,
)
agent = Agent(
model=Gemini(id="gemini-3.5-flash"),
tools=slack.get_tools(),
instructions=slack.instructions(),
markdown=True,
)
async def main() -> None:
print(f"slack.status() = {slack.status()}\n")
search_prompt = "Search Slack for recent discussions about 'deployment'. Summarize the top 3 results."
print(f"> {search_prompt}\n")
await agent.aprint_response(search_prompt)
if __name__ == "__main__":
asyncio.run(main())Run the Example
Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activateInstall dependencies
uv pip install -U "agno[slack]" google-genaiExport environment variables
export GOOGLE_API_KEY="your_google_api_key_here"
export SLACK_BOT_TOKEN="your_slack_bot_token_here"Configure Slack access
Install your Slack app in a test workspace. For public-channel history, grant the bot channels:read, channels:history, and users:read, then invite it to a test channel. To run the supplied search prompt, also grant your app the user-token scope search:read and export that user token:
export SLACK_USER_TOKEN="xoxp-your-user-token"For a bot-only run, replace search_prompt with a request to summarize recent messages in the test channel the bot has joined. Media operations need their corresponding Slack file scopes when you add a media prompt.
Run the example
Save the code above as slack_search_media.py, then run:
python slack_search_media.pyFull source: cookbook/12_context/06_slack_search_media.py