# Interfaces (/features/interfaces)



Product and support teams can expose the same component in an application, team chat, and customer channels. AgentOS interfaces connect components to Slack, Telegram, WhatsApp, A2A, and AG-UI. Each interface handles surface-specific routing and session IDs. Chat interfaces verify their own webhooks; protocol interfaces use AgentOS authorization when it is enabled.

Session history stays tied to each surface's `session_id`.

## Available interfaces [#available-interfaces]

Two categories. Chat surfaces meet humans where they already are. Protocol surfaces are how other systems talk to your agent.

### Chat surfaces [#chat-surfaces]

| Interface    | Use case                                                                                             | Setup                                                  |
| ------------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| **Slack**    | Team chat, DMs, channel mentions, thread sessions                                                    | [Slack](/agent-os/interfaces/slack/introduction)       |
| **Telegram** | Personal assistants, mobile chat                                                                     | [Telegram](/agent-os/interfaces/telegram/introduction) |
| **WhatsApp** | Customer support and mobile chat                                                                     | [WhatsApp](/agent-os/interfaces/whatsapp/introduction) |
| **Discord**  | Community servers, gaming, custom commands. Runs in its own process via `agno.integrations.discord`. | [Discord](/agent-os/interfaces/discord/introduction)   |

### Protocol surfaces [#protocol-surfaces]

| Interface | Use case                                                               | Setup                                            |
| --------- | ---------------------------------------------------------------------- | ------------------------------------------------ |
| **A2A**   | Other agents talk to yours over a standardized agent-to-agent protocol | [A2A](/agent-os/interfaces/a2a/introduction)     |
| **AG-UI** | Browser clients consuming SSE streams of run output                    | [AG-UI](/agent-os/interfaces/ag-ui/introduction) |

## Setup [#setup]

Each interface registers its own routes on the FastAPI app. Slack lands events at `/slack/events`. Telegram at `/telegram/webhook`. The `agent=...` parameter tells the interface which agent to dispatch incoming messages to.

```python
from agno.os import AgentOS
from agno.os.interfaces.slack import Slack
from agno.os.interfaces.telegram import Telegram

agent_os = AgentOS(
    agents=[agent],
    db=db,
    interfaces=[
        Slack(agent=agent, token="xoxb-...", signing_secret="..."),
        Telegram(agent=agent, token="bot-token"),
    ],
)
```

Before registering Telegram’s webhook, set `TELEGRAM_WEBHOOK_SECRET_TOKEN` on the server and send the same value as `secret_token` to Telegram’s `setWebhook` API. The interface reads this secret from the environment; it is not a `Telegram` constructor parameter. Install each interface’s dependencies as described in its setup guide.

If your AgentOS has multiple agents, wire each interface to a different one (Slack to your customer support agent, Telegram to a personal assistant) or wire several interfaces to the same agent.

## Credentials at a glance [#credentials-at-a-glance]

Per-interface setup pages have the full OAuth flows, scope lists, and webhook configuration. The summary:

| Interface | Needs                                                                                                           |
| --------- | --------------------------------------------------------------------------------------------------------------- |
| Slack     | Bot token (`xoxb-...`), signing secret, OAuth scopes for the events you handle                                  |
| Telegram  | Bot token from @BotFather and `TELEGRAM_WEBHOOK_SECRET_TOKEN`, matching the registered webhook secret           |
| WhatsApp  | Business API token, verify token, phone number ID, and `WHATSAPP_APP_SECRET` for inbound signature verification |
| Discord   | Bot token (`DISCORD_BOT_TOKEN`)                                                                                 |
| A2A       | None by default; behind AgentOS JWT auth when `authorization=True`                                              |
| AG-UI     | None by default; behind AgentOS JWT auth when `authorization=True`                                              |

## Sessions per surface [#sessions-per-surface]

Every interface maps surface state to AgentOS sessions, so a conversation in Slack carries forward like any other session. Accepted replies in the same thread reuse its session. Slack defaults to `reply_to_mentions_only=True`, so channel replies still need an @mention; direct messages do not. Set `reply_to_mentions_only=False` and subscribe to the appropriate message events to handle unmentioned channel replies. Persist the component’s sessions and enable history context when the agent should use previous messages.

| Interface | Session ID                                                                                            | User ID                                         |
| --------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| Slack     | `<entity_id>:<channel_id>:<thread_ts>`; existing legacy `<entity_id>:<thread_ts>` sessions are reused | Slack user ID, or resolved email when enabled   |
| Telegram  | `tg:<entity_id>:<chat_id>` with an optional topic suffix; `/new` adds a unique suffix                 | Telegram user ID                                |
| WhatsApp  | `wa:<entity_id>:<user_id>`; a new conversation can add a unique suffix                                | Phone number or encrypted user ID               |
| Discord   | Thread ID                                                                                             | Discord user ID                                 |
| A2A       | A2A context ID                                                                                        | JWT subject, or request metadata when anonymous |
| AG-UI     | Client thread ID                                                                                      | JWT subject, or client-supplied when anonymous  |

Slack can resolve a member's email as `user_id` when `resolve_user_identity=True`. See the [Slack interface guide](/agent-os/interfaces/slack/introduction) for identity and permission setup.

## One agent, many surfaces [#one-agent-many-surfaces]

A single agent can answer on every surface at once:

```python
agent_os = AgentOS(
    agents=[support_agent],
    db=db,
    interfaces=[
        Slack(agent=support_agent, token=..., signing_secret=...),
        Telegram(agent=support_agent, token=...),
        Whatsapp(agent=support_agent, access_token=..., verify_token=...),
        AGUI(agent=support_agent),
    ],
)
```

When user memory is enabled and each interface resolves the same person to the same `user_id`, stored memories are available across surfaces. Session history stays scoped to each surface's `session_id`, and interfaces pass surface context along with the run, such as the Slack channel name.

## Conditional registration [#conditional-registration]

Register optional interfaces only when their credentials are available. In this example, the uppercase names are values your application reads from its environment:

```python
interfaces = []

if SLACK_TOKEN and SLACK_SIGNING_SECRET:
    interfaces.append(Slack(agent=agent, token=SLACK_TOKEN, signing_secret=SLACK_SIGNING_SECRET))

if TELEGRAM_TOKEN and TELEGRAM_WEBHOOK_SECRET_TOKEN:
    interfaces.append(Telegram(agent=agent, token=TELEGRAM_TOKEN))

agent_os = AgentOS(agents=[agent], db=db, interfaces=interfaces)
```

The [Scout](/deploy/templates/scout/overview), [Dash](/deploy/templates/dash/overview), and [Coda](/deploy/templates/coda/overview) apps use this pattern. The Slack interface loads when both environment variables are set, which keeps development runs working before optional channel credentials are configured.

## Custom interfaces and one-off webhooks [#custom-interfaces-and-one-off-webhooks]

Subclass `BaseInterface`, return your routes from `get_router`, and dispatch incoming messages to the agent. See [BaseInterface](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/os/interfaces/base.py) for the full surface.

Add a route directly to the FastAPI app for an application-specific event. This illustrates dispatch only; a provider webhook also needs its request-signature verification before calling the agent:

```python
app = agent_os.get_app()

@app.post("/webhooks/stripe")
async def handle_stripe(event: dict):
    response = await agent.arun(f"Process Stripe event: {event}", user_id="system")
    return {"ok": True, "response": response.content}
```

| Need                                                | Pattern                  |
| --------------------------------------------------- | ------------------------ |
| Reusable surface shared across AgentOS applications | Subclass `BaseInterface` |
| One application-specific event source               | Add a FastAPI route      |
