Skip to main content
An agent with Slack channel notifications.

Create a Slack channel helper

import os
from polos import Polos, SlackChannel, SlackChannelConfig

slack_bot_token = os.environ["SLACK_BOT_TOKEN"]
default_channel = os.environ.get("SLACK_CHANNEL", "#agent-notifications")
ops_channel = os.environ.get("SLACK_OPS_CHANNEL", "#ops-approvals")

# Helper to create a Slack channel targeting a specific Slack channel
def slack(channel: str) -> SlackChannel:
    return SlackChannel(SlackChannelConfig(
        bot_token=slack_bot_token,
        default_channel=channel,
    ))

Define tools

A tool with approval: 'always' suspends for approval before execution. Per-tool channels route approval notifications to a specific Slack channel.
from pydantic import BaseModel, Field
from polos import WorkflowContext, tool

class SendEmailInput(BaseModel):
    to: str = Field(description="Recipient email address")
    subject: str = Field(description="Email subject line")
    body: str = Field(description="Email body text")

# Tool with approval: 'always' — Slack shows inline Approve/Reject buttons.
@tool(
    id="send_email",
    description="Send an email to a recipient. Requires approval before sending.",
    approval="always",
)
async def send_email(ctx: WorkflowContext, input: SendEmailInput) -> dict:
    return {"sent": True, "to": input.to, "subject": input.subject}

Define the agent

from polos import Agent

assistant_agent = Agent(
    id="slack-assistant",
    provider="anthropic",
    model="claude-sonnet-4-5",
    system_prompt=(
        "You are a helpful assistant that can send emails. "
        "When asked to send an email, use the send_email tool. "
        "Be concise and direct."
    ),
    tools=[send_email],
)

Start the worker with Slack channel

import asyncio

async def main():
    main_slack = SlackChannel(SlackChannelConfig(
        bot_token=slack_bot_token,
        default_channel=default_channel,
    ))

    polos = Polos(
        deployment_id="slack-channel-example",
        channels=[main_slack],
    )

    await polos.serve()

asyncio.run(main())

Channel routing

TriggerWhere notifications go
send_email tool approval#ops-approvals (per-tool channel)
When a user @mentions the bot in Slack, the orchestrator parses the agent ID and routes output back to the thread. Tool-level channels override the default.

Run it

git clone https://github.com/polos-dev/polos.git
cd polos/python-examples/23-slack-channel
cp .env.example .env  # Add your POLOS_PROJECT_ID and SLACK_BOT_TOKEN
uv sync
python main.py
See Slack Integration for full Slack app setup instructions (creating the app, adding scopes, enabling interactivity).
Open http://localhost:5173 to view your agents and workflows, run them from the UI, and see execution traces. Python example on GitHub | TypeScript example on GitHub