How to integrate Discordbot MCP with Pydantic AI

Framework Integration Gradient
Discordbot Logo
Pydantic AI Logo
divider

Introduction

This guide walks you through connecting Discordbot to Pydantic AI using the Composio tool router. By the end, you'll have a working Discordbot agent that can add reaction emoji to welcome message, bulk delete spam messages in general channel, assign moderator role to user instantly, create auto moderation rule for links through natural language commands.

This guide will help you understand how to give your Pydantic AI agent real control over a Discordbot account through Composio's Discordbot MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

TL;DR

Here's what you'll learn:
  • How to set up your Composio API key and User ID
  • How to create a Composio Tool Router session for Discordbot
  • How to attach an MCP Server to a Pydantic AI agent
  • How to stream responses and maintain chat history
  • How to build a simple REPL-style chat interface to test your Discordbot workflows

What is Pydantic AI?

Pydantic AI is a Python framework for building AI agents with strong typing and validation. It leverages Pydantic's data validation capabilities to create robust, type-safe AI applications.

Key features include:

  • Type Safety: Built on Pydantic for automatic data validation
  • MCP Support: Native support for Model Context Protocol servers
  • Streaming: Built-in support for streaming responses
  • Async First: Designed for async/await patterns

What is the Discordbot MCP server, and what's possible with it?

The Discordbot MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Discordbot account. It provides structured and secure access to your Discord servers, so your agent can perform actions like moderating users, managing roles, handling group messages, triggering auto-moderation, and automating channel maintenance on your behalf.

  • User moderation and banning: Instruct your agent to ban or bulk ban users, delete their recent messages, and keep your community safe from unwanted behavior.
  • Role and membership management: Automatically assign roles, add users to servers or threads, and update member information to streamline onboarding and permissions.
  • Automated message handling: Let your agent bulk delete messages in a channel or add emoji reactions to keep conversations tidy and interactive.
  • Custom command creation: Enable your agent to create new global application commands, so your Discord server can respond to custom triggers and workflows.
  • Auto moderation rule setup: Have your agent set up or update auto moderation rules for your guild, ensuring safe and compliant community interactions around the clock.

Supported Tools & Triggers

Tools
Add recipient to group channelAdds a user to a discord group direct message (dm) channel.
Update guild member informationAdds a user (who is not already a member) to a guild using their `access token` (which must have `guilds.
Assign role to guild memberAssigns a role to a guild member, provided the bot has 'manage roles' permission in the guild and the role to be assigned is hierarchically lower than the bot's highest role.
Add reaction to messageAdds an emoji reaction from the authenticated user/bot to a specific message in a discord channel; does not return information about existing reactions.
Add or update thread memberAdds a user to a specific, unarchived thread; the user must have access to the thread's parent channel, and for private threads, the bot must already be a member.
Modify guild ban settingsPermanently bans a user from a discord guild, optionally deleting their recent messages (specify deletion period in seconds or days, not both).
Bulk ban users in guild with message deletion optionBans up to 200 users from a discord guild, optionally deleting their recent messages; the bot must have 'ban members' permission in the guild, and this action is irreversible.
Bulk delete messages in channelAtomically bulk deletes messages in a discord channel for moderation or maintenance; deletion may not be instantaneous and messages are unrecoverable.
Create application command objectsCreates a new global discord application command, accessible across guilds and in dms (if `dm permission` is true), noting global commands can take up to an hour to propagate and have registration limits; for guild-specific commands, use a different action.
Create guild auto moderation ruleCreates a new auto moderation rule for a discord guild, requiring 'manage guild' permission; rule parameters are passed in the json request body (see request schema description for body content).
Create channel inviteCreates a new invite for the specified discord channel, provided the bot has 'create instant invite' permission for that channel.
Initiate user channel with recipientCreates a new direct message (dm) channel or retrieves an existing one, using `recipient id` for a 1-on-1 dm or `access tokens` for a group dm; this action only establishes or fetches the channel and does not send messages.
Create new guild objectCreates a new discord guild (server) with the specified name, roles, and channels; icon must be a base64 encoded 128x128 image, and if `afk channel id` is set, `afk timeout` must also be set.
Create guild application commandCreates a new guild-specific application command (slash, user, or message) in discord; command name must be unique per type within the guild (max 100 total commands), and client ui updates may take up to an hour.
Create guild channelCreates a new discord channel (text, voice, category, etc.
Create guild emojiCreates a new custom emoji in a specified discord guild, requiring `create expressions` permission and adherence to guild emoji limits.
Post guild template by codeCreates a new discord guild by applying channels, roles, and settings from a specified, valid, and accessible guild template code.
Create role with guild idCreates a new role in a discord guild with customizable name, permissions, color, hoist, mentionability, and icon; `icon` (custom image hash) and `unicode emoji` (standard emoji) are mutually exclusive.
Create guild scheduled eventCreates a new scheduled event in a discord guild; a separate json request body (not defined in this action's request schema model) with event details (e.
Create guild stickerUploads a png, apng, or lottie json file (max 512kb) as a new custom sticker to the specified discord guild; requires 'manage expressions' permissions and sufficient server boost level for sticker slots.
Create guild templateCreates a template of an existing discord guild's structure (settings, roles, channels) but not its content (e.
Post interaction callbackSends a response to a discord interaction (e.
Post message to channelSends a message to a specified discord channel (text, embeds, stickers, components, attachments); requires `send messages` permission and one of `content`, `embeds`, `sticker ids`, or `attachments`.
Create stage instanceCreates a new stage instance in a specified stage channel for live audio events; requires `manage channels`, `mute members`, and `move members` permissions in the channel.
Create new thread in channelCreates a new thread in a text or announcement discord channel; requires a 'name' and optionally other details (e.
Create thread in message channelCreates a new thread from a specific message in a discord channel, requiring `create public threads` permission (and `send messages` if in a forum/media channel).
Create channel webhookCreates a webhook in a specified discord channel for external applications to post messages, provided the caller has 'manage webhooks' permission in that channel.
Crosspost channel messageCrossposts a message from an announcement channel to all following channels, provided the message has not been previously crossposted and is not a system message or a message sent by a webhook.
Delete reaction from messageDeletes all reactions (not just the bot's) from a message in a channel; requires 'manage messages' permission.
Delete channel message reaction by emojiRemoves all reactions for a specific emoji from a message in a discord channel; requires 'manage messages' permission and this operation is irreversible.
Delete application commandPermanently deletes a specific application command; this action is irreversible.
Delete guild auto moderation ruleDeletes a specific auto-moderation rule from a discord guild.
Delete channel by idPermanently deletes a discord channel by its id; this action is irreversible and the channel must exist and be deletable.
Delete channel permission overrideDeletes a specific user's or role's permission overwrite in a discord channel, reverting their permissions to default; this action is irreversible.
Delete channel recipientPermanently removes a user from an accessible discord group dm channel, revoking their access.
Delete guild by idPermanently deletes a specified discord guild (server); the authenticated user must be the owner of the guild.
Delete guild commandPermanently deletes a specific application command (e.
Delete guild emoji by idPermanently deletes a specified custom emoji from a guild, requiring 'manage expressions' permissions; cannot delete default emojis and is irreversible.
Delete guild integrationPermanently deletes a specific, unwanted or problematic integration from a discord guild; requires 'manage server' or 'administrator' permissions.
Delete guild member by idRemoves (kicks) a member from a discord guild; the user must be an existing member of the specified guild, and this action is permanent.
Delete guild member roleRemoves a specified role from a member of a discord guild, provided the member currently possesses that role.
Delete role from guildPermanently deletes a specified role from a discord guild, revoking it from all members; requires 'manage roles' permission and the target role must be lower in hierarchy than the bot's highest role.
Delete guild scheduled eventPermanently deletes a specific scheduled event from a discord guild; this action is irreversible.
Delete guild stickerPermanently deletes a custom sticker from a discord guild; the specified guild and sticker must exist, and this action is irreversible.
Delete guild template by codeDeletes an existing guild template by its unique code from a specified guild, returning the deleted template's details.
Delete channel messagePermanently and irreversibly deletes a message from a specified discord channel.
Delete user reaction on messageRemoves the authenticated user's own emoji reaction, which they must have previously added, from a specific message in a discord channel; this action is irreversible and cannot remove others' reactions.
Delete original webhook messagePermanently deletes an existing original message posted by a webhook (using its id and token), optionally within a specific thread.
Delete stage instance by channel idDeletes the stage instance for the given `channel id`, permanently ending its live audio event.
Delete channel thread memberRemoves a user from a specified, unarchived thread in a discord channel.
Delete user reaction from messageRemoves a specific user's emoji reaction from a message; requires 'manage messages' permission if deleting reactions from other users.
Delete webhook by idPermanently deletes a specified, existing discord webhook by its unique id; this action is irreversible.
Delete webhook using id and tokenPermanently deletes a discord webhook specified by its id and token; this action is irreversible.
Delete webhook messageDeletes a message previously sent by the specified webhook, optionally within a specific thread.
Github action webhooks processingForwards github event notifications to a discord channel via a webhook configured for github-formatted payloads (url ending in `/github`).
Post to slack webhookSends richly formatted messages to discord via its slack-compatible webhook endpoint; requires at least one of `text` or `attachments` and adherence to content limits.
Post webhook with embeds and componentsExecutes a discord webhook to send messages, embeds, or interactive components to a specific discord channel or thread.
Add follower to channel via webhookFollows a specified announcement channel (`channel id`), relaying its messages to `webhook channel id` in the current server; requires 'manage webhooks' permission in the current server and that it has community features enabled.
List active threads in guildRetrieves all currently active and visible threads within a specified discord guild, excluding archived or hidden threads.
Retrieve application detailsRetrieves the full details of a discord application using its unique `application id`.
Fetch application command by idFetches the details of a specific, existing application command, identified by its application snowflake id and command snowflake id.
Retrieve application role metadataRetrieves all role connection metadata records for a given discord application id; an empty list is returned if none are configured.
Get user role connectionFetches the role connection object for the current user for a specified discord application.
Retrieve auto moderation ruleRetrieves the complete configuration details of a specific auto-moderation rule within a discord guild for inspection or verification.
Retrieve bot gatewayRetrieves the wss url, recommended shard count, and session start limits, which are prerequisite for a bot to connect to the discord gateway and receive events.
Retrieve channel detailsRetrieves detailed metadata for a specific discord channel using its `channel id`, which must be a valid and accessible channel id; note that this action returns only channel metadata, not message content or member lists.
Get gateway detailsRetrieves the websocket url to connect to discord's gateway for receiving real-time events.
Retrieve guild detailsRetrieves detailed information for a specified discord guild (server) by its `guild id`, optionally including approximate member and presence counts if `with counts` is true.
Fetch guild application command by idFetches detailed information for a specific application command within a discord guild, identified by `application id`, `guild id`, and `command id`.
Retrieve guild command permissionsFetches the permissions for a specific application command within a guild, used to inspect its current access settings.
Retrieve guild user ban detailsFetches the ban details for a specific user in a discord guild, if that user is currently banned.
Fetch emoji by guild and idRetrieves details for a specific custom emoji within a specified discord guild, requiring valid and accessible guild and emoji ids.
Retrieve guild member by user idRetrieves detailed information for a specific member of a discord guild, provided the bot belongs to the guild and has necessary permissions (e.
Retrieve guild new member welcomeRetrieves the configured new member welcome screen for a discord guild, detailing the welcome message, suggested member actions, and resource channels.
Preview guild by idFetches a public preview of a discord guild by its id, if the guild has the preview feature enabled.
Get guild scheduled event by idRetrieves a specific scheduled event from a discord guild by its id, optionally including the count of subscribed users.
Get guild onboarding by idRetrieves the onboarding settings for a specified discord guild, including prompts, options, default channels, and enabled status, to examine its new member guidance process when the guild id is known and accessible.
Retrieve sticker from guildRetrieves a specific sticker from a discord guild using the guild and sticker ids; requires the sticker to exist in the guild.
Retrieve guild template with codeRetrieves the complete structure and details of a discord guild template using its unique code; the code must be valid and refer to an existing, accessible template.
Retrieve guild vanity urlFetches the vanity url, including the invite `code` and its `uses` count, for a given discord `guild id`, which must correspond to an existing guild.
Retrieve guild webhooksRetrieves all webhook objects for a specified discord guild; requires 'manage webhooks' permission for the authenticated entity.
Retrieve guild welcome screenRetrieves the configured welcome screen for a specific discord guild that has the 'community' feature enabled.
Retrieve guild widget jsonRetrieves the public json widget data for a discord guild, if the widget is enabled for that guild.
Retrieve guild widget informationRetrieves the widget settings for a specified discord guild, indicating if the widget is enabled and its configured channel id; requires a valid `guild id`.
Retrieve message from channelRetrieves a specific message from a discord channel, identified by `channel id` and `message id`, if the channel and message exist and are accessible.
Get your applicationsRetrieves detailed information about the current authenticated discord application.
Get oauth2 applications for current userRetrieves detailed information about the oauth2 application associated with the current authentication; cannot query other applications.
Retrieve original webhook messageFetches the original, unedited message posted by a specific discord webhook, requiring a message to have been previously sent by this webhook and to exist in the specified thread if `thread id` is provided.
Get oauth2 keysRetrieves discord's oauth2 public keys (jwk format) for verifying access tokens; keys may rotate, so refresh caches periodically.
Retrieve stage instance by channel idGets the active stage instance for a given stage channel id.
Retrieve sticker by idRetrieves a specific discord sticker by its unique id.
Retrieve thread member by idRetrieves a member from a specified thread using their user id, optionally including the full guild member object.
Retrieve user by idFetches public information for a discord user, requiring a valid and existing user id (snowflake).
Retrieve webhook by idRetrieves detailed information for an existing discord webhook, identified by its unique id, to verify settings or manage the webhook.
Retrieve webhook informationFetches a discord webhook's configuration details (e.
Retrieve webhook message by idRetrieves a specific message previously sent by a discord webhook using its `message id`, requiring `thread id` if the message is part of a thread.
Retrieve invite by codeResolves a discord invite code to get its details, optionally including member counts or data for a specific guild scheduled event; visibility of some details may depend on bot permissions.
Delete invite via codeRevokes a discord server invite using its unique code, permanently preventing new joins via this link (does not affect existing members); requires 'manage server' or 'manage invites' permissions on the server.
Update thread membershipJoins the authenticated user to a thread specified by `channel id`; use this when the user is not already a member, for archived threads, or for threads requiring explicit joining, provided the thread is joinable, not locked or full, and the user has permissions.
Delete user guildEnables the authenticated user to leave a specified discord guild of which they are a member but not the owner; this action is irreversible.
Remove current user from threadRemoves the currently authenticated user from a specified, existing, and accessible discord thread of which they are currently a member.
List commands for applicationFetches all global application commands for the specified discord application id; does not fetch guild-specific commands.
Retrieve guild auto moderation rulesFetches all auto moderation rules for a specified discord guild to review or audit its configuration; requires `view audit log` permissions and the action does not modify rules.
List Channel InvitesFetches all active invites for a given discord channel id (read-only), requiring channel invite view permissions; response object structures may vary.
Retrieve channel webhooksFetches detailed information for all webhooks in a given valid discord channel, useful for review or auditing purposes.
Get application guild command permissionsCall this action to retrieve all explicitly set guild-level permission settings for all commands of a specific application within a given guild, typically for auditing or troubleshooting command access.
Fetch guild commands via application idFetches all application command definitions (slash, user, and message types) for a specific application within a given discord guild, optionally including localizations; does not return permissions or usage statistics.
Get guild audit logs by guild idRetrieves audit log entries (e.
List guild bansFetches a list of users banned from a specified discord guild; `before`/`after` parameters require user ids from previous results for correct pagination.
Retrieve guild channelsFetches all channels (e.
Retrieve guild emojisFetches all custom emoji objects for a specified discord guild if the bot has access; returns only custom guild emojis, not standard unicode or nitro emojis.
List guild integrationsLists all integration objects for a specified discord guild.
Retrieve guild invites by idRetrieves all currently active invite codes for a specified discord guild, typically for administration, analytics, or managing guild invitations.
Get guild membersRetrieves members for a discord guild; requires a valid guild id for an existing guild.
List guild rolesFetches all roles in a discord guild, providing details for each role but not user assignments; `guild id` must be valid.
Retrieve guild scheduled eventsRetrieves a list of scheduled events for a specified discord guild, optionally including subscribed user counts, provided the authenticated user/bot has access to the guild.
Retrieve users for scheduled eventFetches users who have expressed interest in a specific scheduled event, requiring valid guild and event ids.
Retrieve guild stickersRetrieves all custom sticker objects for a discord guild; does not include standard/nitro stickers.
Get guild templates by guild idRetrieves all guild templates for an existing discord guild, specified by its id.
List guild regionsFetches a list of available voice regions for a specified discord guild.
Get channel message reaction by emojiFetches a list of users who reacted to a specific message with a given emoji in a discord channel; retrieves users for one emoji at a time.
Fetch messages from channelRetrieves historical messages from a specified, accessible discord channel, typically newest first; for real-time messages, use discord's websocket gateway api.
Get private archived threads for userRetrieves private archived threads from a specified channel that the current user is a member of.
Retrieve pinned messages in channelRetrieves all currently pinned messages from a discord channel using its valid, existing id; typically limited to 50 messages, and no history of past pins is returned.
Get archived private threads by channel idLists a channel's private archived threads, sorted by most recent archival, requiring view access to them.
Get archived public threads by channel idLists public archived threads in an accessible discord channel, returning an empty list if none exist; does not list private or active threads.
List sticker packsFetches sticker packs available to nitro subscribers on discord, excluding custom or guild-specific ones.
List thread members in channelRetrieves members of a specified discord thread, with an option to include full guild member objects for each.
Fetch voice regions listLists all available discord voice regions with their id, name, operational status (custom, deprecated, optimal), noting that availability may vary by server.
Pin message in channelPins a message in a discord channel for increased visibility, if the channel's pin limit (typically 50) is not exceeded.
Retrieve guild prune infoPreviews the number of members that would be pruned from a discord guild based on inactivity days and optional roles; this action only returns a count and does not remove members.
Prune guild members by rolesRemoves inactive members from a discord guild, requiring 'kick members' permission; use `compute prune count=true` to preview results before actual removal.
Update guild onboarding configurationConfigures or updates a discord guild's new member onboarding flow, including defining prompts with options, assigning roles/channels, setting default channels, and managing the flow's active status.
Search guild members by idSearches for members in a specific discord guild, allowing filtering by a query string.
Modify channel permissionsUpdates or creates a permission overwrite for a role (type `0`) or member (type `1`) specified by `overwrite id` within an existing discord channel (`channel id`), using `allow` and `deny` bitwise values to precisely control permissions.
Update guild template by codeSynchronizes a guild template (by `code`) with its source guild (`guild id`), updating it to match the source's current configuration; this does not affect guilds already created from this template.
Trigger typing indicatorShows the bot is 'typing' in a discord channel, typically before sending a message; indicator stops after 10 seconds or upon message send, so use when actively preparing a response.
Delete guild user banRevokes a ban for a user from a discord guild, allowing them to rejoin if they choose.
Delete channel message pinUnpins a message that is currently pinned in a specified discord channel; the message itself is not deleted.
Modify application by idUpdates a discord application's settings using its `application id`; `max participants` requires the `application embedded activities` flag, and `team id`, `type`, or `install params` must be `null` if specified.
Patch command for applicationUpdates specified properties of a discord application command (e.
Update user application role connectionUpdates the authorized user's role connection for a specific application, which must have a linked role connection configured.
Modify guild auto moderation ruleUpdates an existing auto-moderation rule, identified by `guild id` and `rule id` in the path, with new values for rule properties (e.
Patch channel properties by idPartially updates an existing discord channel, using `channel id` for identification and properties in the request body for changes, ensuring these properties are applicable to the channel's type.
Update guild settingsUpdates settings for a discord guild, such as its name, region, or icon; transferring ownership requires being the current owner, and managing features or certain visual elements (e.
Update application guild commandUpdates a specific discord application command's properties (like name, description, options, or permissions) within a given guild; `application id`, `guild id`, and `command id` must refer to valid entities.
Update guild emoji rolesUpdates a custom emoji's name and/or role restrictions in a discord guild; cannot create or delete emojis, and role updates for managed emojis may be restricted by their integration.
Modify guild member detailsUpdates a guild member's attributes (e.
Modify guild roleUpdates a discord guild role's attributes (name, permissions, color, etc.
Update guild scheduled eventUpdates attributes such as name, description, schedule, status, or location for an existing discord guild event; only fields in the request body are changed.
Update guild sticker infoModifies a guild sticker's name, description, or tags, requiring 'manage emojis and stickers' permission.
Patch guild template informationUpdates a discord guild template's `name` and/or `description` given its `guild id` and template `code`; omitted fields retain current values, and an empty string for `description` clears it.
Update guild welcome screenUpdates a guild's welcome screen, including its description, enabled status, and up to 5 welcome channels; when specifying channel emojis, use `emoji name` as `emoji id` must be `null` if sent.
Patch guild widget endpointUpdates an existing discord guild's widget settings, such as its enabled state or clearing its invite channel.
Update channel messageUpdates a message previously sent by the bot in a discord channel, by modifying its content, embeds, components, flags, or attachment metadata (new attachments cannot be uploaded); only provide fields to change, using null or an empty list to clear existing values.
Update application descriptionModifies settings for the current authenticated discord application (e.
Modify guild member nicknameModifies the nickname of the currently authenticated user within a specified discord guild.
Update current user profileUpdates the current authenticated user's discord username and/or avatar.
Patch webhook original messageUpdates the original editable message previously sent by a webhook, allowing partial modification of its content (max 2000 chars), embeds (max 10), attachments (kept by `id`, metadata updatable), components, allowed mentions, and flags.
Modify guild voice state for meUpdates the current user's voice state in a guild (e.
Patch guild voice stateUpdates a user's voice state in a discord guild, such as toggling server mute or disconnecting from a voice channel; requires `mute members` permission to change mute status or `move members` to disconnect.
Update webhook details patchUpdates properties (e.
Update webhook name and avatarUpdates the default name and/or avatar for an existing discord webhook, using its id and token.
Update discord message with webhookUpdates a message previously sent by the *same* webhook, allowing partial modification of content, embeds, attachments, or components; will not edit user/bot messages.

What is the Composio tool router, and how does it fit here?

What is Tool Router?

Composio's Tool Router helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Tool Router

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Tool Router works

The Tool Router follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Prerequisites

Before starting, make sure you have:
  • Python 3.9 or higher
  • A Composio account with an active API key
  • Basic familiarity with Python and async programming

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key. You'll need credits to use the models, or you can connect to another model provider.
  • Keep the API key safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Navigate to your API settings and generate a new API key.
  • Store this key securely as you'll need it for authentication.

Install dependencies

bash
pip install composio pydantic-ai python-dotenv

Install the required libraries.

What's happening:

  • composio connects your agent to external SaaS tools like Discordbot
  • pydantic-ai lets you create structured AI agents with tool support
  • python-dotenv loads your environment variables securely from a .env file

Set up environment variables

bash
COMPOSIO_API_KEY=your_composio_api_key_here
USER_ID=your_user_id_here
OPENAI_API_KEY=your_openai_api_key

Create a .env file in your project root.

What's happening:

  • COMPOSIO_API_KEY authenticates your agent to Composio's API
  • USER_ID associates your session with your account for secure tool access
  • OPENAI_API_KEY to access OpenAI LLMs

Import dependencies

python
import asyncio
import os
from dotenv import load_dotenv
from composio import Composio
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStreamableHTTP

load_dotenv()
What's happening:
  • We load environment variables and import required modules
  • Composio manages connections to Discordbot
  • MCPServerStreamableHTTP connects to the Discordbot MCP server endpoint
  • Agent from Pydantic AI lets you define and run the AI assistant

Create a Tool Router Session

python
async def main():
    api_key = os.getenv("COMPOSIO_API_KEY")
    user_id = os.getenv("USER_ID")
    if not api_key or not user_id:
        raise RuntimeError("Set COMPOSIO_API_KEY and USER_ID in your environment")

    # Create a Composio Tool Router session for Discordbot
    composio = Composio(api_key=api_key)
    session = composio.create(
        user_id=user_id,
        toolkits=["discordbot"],
    )
    url = session.mcp.url
    if not url:
        raise ValueError("Composio session did not return an MCP URL")
What's happening:
  • We're creating a Tool Router session that gives your agent access to Discordbot tools
  • The create method takes the user ID and specifies which toolkits should be available
  • The returned session.mcp.url is the MCP server URL that your agent will use

Initialize the Pydantic AI Agent

python
# Attach the MCP server to a Pydantic AI Agent
discordbot_mcp = MCPServerStreamableHTTP(url, headers={"x-api-key": COMPOSIO_API_KEY})
agent = Agent(
    "openai:gpt-5",
    toolsets=[discordbot_mcp],
    instructions=(
        "You are a Discordbot assistant. Use Discordbot tools to help users "
        "with their requests. Ask clarifying questions when needed."
    ),
)
What's happening:
  • The MCP client connects to the Discordbot endpoint
  • The agent uses GPT-5 to interpret user commands and perform Discordbot operations
  • The instructions field defines the agent's role and behavior

Build the chat interface

python
# Simple REPL with message history
history = []
print("Chat started! Type 'exit' or 'quit' to end.\n")
print("Try asking the agent to help you with Discordbot.\n")

while True:
    user_input = input("You: ").strip()
    if user_input.lower() in {"exit", "quit", "bye"}:
        print("\nGoodbye!")
        break
    if not user_input:
        continue

    print("\nAgent is thinking...\n", flush=True)

    async with agent.run_stream(user_input, message_history=history) as stream_result:
        collected_text = ""
        async for chunk in stream_result.stream_output():
            text_piece = None
            if isinstance(chunk, str):
                text_piece = chunk
            elif hasattr(chunk, "delta") and isinstance(chunk.delta, str):
                text_piece = chunk.delta
            elif hasattr(chunk, "text"):
                text_piece = chunk.text
            if text_piece:
                collected_text += text_piece
        result = stream_result

    print(f"Agent: {collected_text}\n")
    history = result.all_messages()
What's happening:
  • The agent reads input from the terminal and streams its response
  • Discordbot API calls happen automatically under the hood
  • The model keeps conversation history to maintain context across turns

Run the application

python
if __name__ == "__main__":
    asyncio.run(main())
What's happening:
  • The asyncio loop launches the agent and keeps it running until you exit

Complete Code

Here's the complete code to get you started with Discordbot and Pydantic AI:

import asyncio
import os
from dotenv import load_dotenv
from composio import Composio
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStreamableHTTP

load_dotenv()

async def main():
    api_key = os.getenv("COMPOSIO_API_KEY")
    user_id = os.getenv("USER_ID")
    if not api_key or not user_id:
        raise RuntimeError("Set COMPOSIO_API_KEY and USER_ID in your environment")

    # Create a Composio Tool Router session for Discordbot
    composio = Composio(api_key=api_key)
    session = composio.create(
        user_id=user_id,
        toolkits=["discordbot"],
    )
    url = session.mcp.url
    if not url:
        raise ValueError("Composio session did not return an MCP URL")

    # Attach the MCP server to a Pydantic AI Agent
    discordbot_mcp = MCPServerStreamableHTTP(url, headers={"x-api-key": COMPOSIO_API_KEY})
    agent = Agent(
        "openai:gpt-5",
        toolsets=[discordbot_mcp],
        instructions=(
            "You are a Discordbot assistant. Use Discordbot tools to help users "
            "with their requests. Ask clarifying questions when needed."
        ),
    )

    # Simple REPL with message history
    history = []
    print("Chat started! Type 'exit' or 'quit' to end.\n")
    print("Try asking the agent to help you with Discordbot.\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in {"exit", "quit", "bye"}:
            print("\nGoodbye!")
            break
        if not user_input:
            continue

        print("\nAgent is thinking...\n", flush=True)

        async with agent.run_stream(user_input, message_history=history) as stream_result:
            collected_text = ""
            async for chunk in stream_result.stream_output():
                text_piece = None
                if isinstance(chunk, str):
                    text_piece = chunk
                elif hasattr(chunk, "delta") and isinstance(chunk.delta, str):
                    text_piece = chunk.delta
                elif hasattr(chunk, "text"):
                    text_piece = chunk.text
                if text_piece:
                    collected_text += text_piece
            result = stream_result

        print(f"Agent: {collected_text}\n")
        history = result.all_messages()

if __name__ == "__main__":
    asyncio.run(main())

Conclusion

You've built a Pydantic AI agent that can interact with Discordbot through Composio's Tool Router. With this setup, your agent can perform real Discordbot actions through natural language. You can extend this further by:
  • Adding other toolkits like Gmail, HubSpot, or Salesforce
  • Building a web-based chat interface around this agent
  • Using multiple MCP endpoints to enable cross-app workflows (for example, Gmail + Discordbot for workflow automation)
This architecture makes your AI agent "agent-native", able to securely use APIs in a unified, composable way without custom integrations.

How to build Discordbot MCP Agent with another framework

FAQ

What are the differences in Tool Router MCP and Discordbot MCP?

With a standalone Discordbot MCP server, the agents and LLMs can only access a fixed set of Discordbot tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Discordbot and many other apps based on the task at hand, all through a single MCP endpoint.

Can I use Tool Router MCP with Pydantic AI?

Yes, you can. Pydantic AI fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Discordbot tools.

Can I manage the permissions and scopes for Discordbot while using Tool Router?

Yes, absolutely. You can configure which Discordbot scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

How safe is my data with Composio Tool Router?

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Discordbot data and credentials are handled as safely as possible.

Used by agents from

Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai

Never worry about agent reliability

We handle tool reliability, observability, and security so you never have to second-guess an agent action.