Talk to your agent in Slack

Connect your personal agent to Slack using an AgentOS interface and ngrok.

Connect the agent from Build your first agent to Slack. You'll keep AgentOS running locally and use ngrok to give Slack an HTTPS endpoint for delivering messages.

You'll need your existing project, a Slack workspace where you can install apps, and an ngrok account.

Create your Slack app

  1. Open Your Apps and select Create New AppFrom a manifest.
  2. Choose your workspace, select JSON, and paste this manifest:
Slack app manifest
{
  "display_information": {
    "name": "Personal Agent",
    "description": "Keep track of your tasks and notes."
  },
  "features": {
    "bot_user": {
      "display_name": "Personal Agent",
      "always_online": true
    },
    "app_home": {
      "home_tab_enabled": false,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "assistant_view": {
      "assistant_description": "Keep track of your tasks and notes.",
      "suggested_prompts": []
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "assistant:write",
        "chat:write",
        "im:history",
        "im:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": false
  }
}
  1. Review the configuration and create the app.
  2. Under OAuth & Permissions, click Install to Workspace and approve the installation. Copy the Bot User OAuth Token, which starts with xoxb-.
  3. Under Basic InformationApp Credentials, reveal and copy the Signing Secret.

The manifest enables direct messages and Slack's chat interface. You'll configure message delivery after starting the server with these credentials.

Configure your local service

Stop your Python server with Ctrl+C. In the same terminal, from your project directory, add the Slack dependencies:

uv add "agno[os,sqlite,slack]==3.0.8"

Generate a separate key for accessing your AgentOS API:

uv run python -c "import secrets; print(secrets.token_urlsafe(32))"

Set the following variables, using that generated value for OS_SECURITY_KEY:

export SLACK_TOKEN="xoxb-your-bot-token"
export SLACK_SIGNING_SECRET="your-slack-signing-secret"
export OS_SECURITY_KEY="your-generated-agentos-key"

Keep OPENAI_API_KEY set from the first page. The OS security key protects the management API when you expose the server through ngrok. Slack authenticates its own requests using the signing secret.

Add these imports to personal_agent.py:

from os import environ

from agno.os.interfaces.slack import Slack

Replace the agent_os = AgentOS(...) line with:

agent_os = AgentOS(
    agents=[agent],
    db=db,
    interfaces=[
        Slack(
            agent=agent,
            token=environ["SLACK_TOKEN"],
            signing_secret=environ["SLACK_SIGNING_SECRET"],
        )
    ],
    tracing=True,
)

Keep the rest of the file, including app = agent_os.get_app() and the __main__ block. Restart the service:

uv run personal_agent.py

Update your local Control Plane connection to use security key authentication with the same OS_SECURITY_KEY. Keep JWT authorization off for this local setup.

Start your ngrok tunnel

Install ngrok using the instructions for your operating system. Open a second terminal and connect it to your account:

ngrok config add-authtoken YOUR_NGROK_AUTHTOKEN
ngrok http 7777

Copy the HTTPS forwarding URL printed by ngrok, such as https://your-domain.ngrok.app. Keep both the Python server and ngrok running.

Tell Slack where to send messages

Return to your app's configuration at Your Apps.

Enable event delivery

Open Event Subscriptions and turn Enable Events on. Set the Request URL to your ngrok URL followed by /slack/events:

https://your-domain.ngrok.app/slack/events

Wait for Verified. The running Slack interface validates Slack's signature and answers its URL verification request.

Under Subscribe to bot events, add:

  • message.im
  • assistant_thread_started

Save your changes. If Slack asks you to reinstall the app, complete that step.

Configure interactions

Open Interactivity & Shortcuts, turn interactivity on, and set its Request URL to:

https://your-domain.ngrok.app/slack/interactions

Save the change. This connects Slack's interactive actions to AgentOS.

Message your agent

In Slack, find Personal Agent under Apps and open its messages. Send:

Add a task to send Maya the revised launch checklist by Friday.
Remember that I prefer short updates with action items first.

Reply in the thread:

I sent the checklist. Mark it complete.

Start a new message outside that thread and ask:

What's on my task list?

The agent should read the saved list and show the checklist as complete. Each Slack thread has its own conversation history; your files carry across threads.

Slack supplies your Slack user ID to the agent. Its files are separate from those created under your Control Plane identity in the first page. Other Slack users get their own files too. You can inspect the Slack conversation in Sessions and its tool calls in Traces using your administrator connection.

If something isn't working

SymptomWhat to check
Slack cannot verify the URLKeep Python and ngrok running. Use the HTTPS URL with /slack/events, and check that SLACK_SIGNING_SECRET belongs to this app.
Slack says messaging is disabledUnder App Home, enable the Messages tab and allow users to send messages. Reopen the app in Slack.
Messages arrive but the agent doesn't respondCheck the Python terminal for errors, confirm OPENAI_API_KEY is set, and verify that message.im is subscribed.
Slack reports missing permissionsCheck the manifest's bot scopes and reinstall the app after adding permissions.
Messages stop arriving after restarting ngrokCompare the current forwarding URL with both saved Slack request URLs. Update them if it changed.
The Control Plane returns UnauthorizedConfigure its security key authentication with the same OS_SECURITY_KEY as the server.

For additional interface options, see the Slack reference.

Next: take it to production

Your agent now responds in Slack while your computer and tunnel are running. Next, deploy it to Render so it stays available when you close your laptop.