* Add Discord hosting channel Add an alpha agent-framework-hosting-discord package backed by Discord HTTP Interactions. The channel verifies signed slash-command requests, registers commands, runs hosted agents and ChannelCommand handlers, supports originating response hooks, streams by editing the original interaction response, and can push through Discord channel ids. Factor standard channel response-hook context application into hosting core so both host fan-out and originating channel replies use one helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Discord review chunking feedback Ensure Discord command replies are chunked and streaming preview edits stay under Discord's content limit while final streamed replies continue through the chunked reply path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * small fix in init * updated lock --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2.5 KiB
agent-framework-hosting-discord
Discord HTTP Interactions channel for agent-framework-hosting.
The channel exposes a signed Starlette route for Discord slash commands, maps a
configurable slash command to the hosted agent, maps ChannelCommand instances
to native Discord commands, and supports push to Discord channel ids.
Usage
from agent_framework_hosting import AgentFrameworkHost
from agent_framework_hosting_discord import DiscordChannel
host = AgentFrameworkHost(
target=my_agent,
channels=[
DiscordChannel(
application_id="<discord application id>",
public_key="<discord public key>",
bot_token="<discord bot token>",
guild_id="<guild id for fast dev command registration>",
)
],
)
host.serve()
Configure the Discord Developer Portal interaction endpoint as:
https://<your-host>/discord/interactions
The channel verifies Discord's X-Signature-Ed25519 header against the raw
request body before parsing JSON. skip_signature_verification=True exists only
for local tests and should not be used on a public endpoint.
Slash commands
By default, /ask prompt:<text> invokes the hosted agent. Additional
ChannelCommand instances are registered as Discord slash commands with an
optional input string option:
from agent_framework_hosting import ChannelCommand
async def reset(ctx):
await ctx.reply("Reset acknowledged")
DiscordChannel(
application_id="...",
public_key="...",
bot_token="...",
commands=[ChannelCommand("reset", "Reset the conversation", reset)],
)
When guild_id is set, commands are registered only for that guild and usually
appear quickly. Global command registration can take much longer to propagate.
If register_commands=True but bot_token is omitted, the channel logs a
warning and assumes commands were registered outside the host.
Identity, sessions, and push
The default isolation key is discord:<guild-or-dm>:<channel_id>:<user_id>,
which keeps each user private inside a Discord channel or thread. Pass
isolation_key_factory= to use a different scope.
ChannelIdentity.native_id is the Discord user id. Push requires
identity.attributes["channel_id"]; the first slice intentionally does not
create DM channels as a fallback.
Streaming
Set streaming=True to consume the host stream and edit the original Discord
interaction response as text accumulates. Edits are debounced with
edit_interval to avoid excessive Discord REST calls.