Discord Source/Output for Waken -- gateway events in, REST message send out.
Project description
waken-discord
Discord Source/Output for Waken --
"nginx for AI agents." Unlike a Target adapter (waken-claude,
waken-gemini, ...), Discord here is a channel: DiscordSource turns
incoming Discord messages into waken Events, and DiscordOutput posts a
Target's Response back to the channel it came from.
Install
pip install waken-discord
Needs a Discord bot application (Discord Developer Portal -> New Application -> Bot):
DISCORD_BOT_TOKEN-- the bot token from the Bot page.- The Message Content privileged gateway intent, enabled on that same
Bot page (under "Privileged Gateway Intents"). This is a real, commonly
missed step -- without it, Discord silently delivers every message with
contentas an empty string (except direct @mentions of the bot), no matter what the bot process itself requests. - The bot invited to your server with, at minimum, the
botscope and the Send Messages/Read Message History permissions.
Usage
from waken import Runtime
from waken_claude import ClaudeAdapter
from waken_discord import DiscordOutput, DiscordSource
runtime = Runtime()
runtime.target("claude", ClaudeAdapter())
runtime.source("discord", DiscordSource(target="claude"))
runtime.output("discord", DiscordOutput())
runtime.run()
DiscordSource/DiscordOutput both resolve DISCORD_BOT_TOKEN from the
environment by default, or accept it as a constructor argument. Every
incoming message becomes an Event(source="discord", target="claude", payload={"prompt": text}, session_id=runtime.session("discord", external_key=str(channel_id)), metadata={"channel_id": channel_id}) --
follow-up messages in the same channel resume the same waken session.
DiscordOutput reads event.metadata["channel_id"] back off to know where
to send the reply.
Messages from bots -- including DiscordOutput's own replies -- are
filtered out before dispatch, otherwise a reply posted back into the
channel would re-trigger DiscordSource and loop forever.
Design notes
A gateway connection for DiscordSource, REST-only for
DiscordOutput. Discord bots receive messages over a persistent gateway
WebSocket -- there's no webhook equivalent of "a message was posted" a bot
can subscribe to instead, so DiscordSource holds that connection open,
the same shape as waken-slack's Socket Mode connection: a background task
started in start(), closed in stop().
Sending a message, however, is a plain REST call authenticated by the bot
token -- it needs no gateway connection at all. DiscordOutput doesn't
spin up a second discord.Client (which would mean logging in twice and
paying for a connection it'd never use) to get one. Instead it talks
directly to discord.http.HTTPClient, the lightweight, gateway-free HTTP
client that discord.py itself builds internally and hangs every
Client's own REST calls off of. It isn't re-exported from
discord/__init__.py or documented as public API the way discord.Client
is, but it's the only thing the library ships that fits "REST send, no
gateway" -- there's no separate public discord.RESTClient. It ships under
the same py.typed package as everything else, so it stays fully
type-checked here regardless.
discord.Client.start(), not .run(). Client.run() is documented as
"a blocking call that abstracts away the event loop initialisation from
you" and calls asyncio.run(...) itself -- it wants to own the whole
process's event loop, the same way Client.run()/SlackSource's
SocketModeHandler.start_async() would. waken's Runtime already owns
the loop this Source runs inside, so DiscordSource.start() instead
schedules the lower-level client.start(token) coroutine (a shorthand for
login() + connect(), and just a plain coroutine with no loop management
of its own) as a background asyncio.Task, and awaits client.close() +
that task on stop() -- the recipe discord.py itself documents for running
inside an already-running event loop.
Why discord.py, not one of its forks. discord.py went through a
period of being unmaintained a few years back, which is what spawned
pycord/nextcord/disnake in the first place -- but it later resumed
active maintenance, and remains, by a wide margin, the most widely used
library in this space (checked directly against all three forks' PyPI
release cadence and GitHub activity before picking it, not from memory).
Development
git clone https://github.com/WakenHQ/waken-discord
cd waken-discord
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
Tests mock discord.py's Client and discord.http.HTTPClient entirely
-- no network access, real gateway connection, or Discord bot token needed
to run the suite.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file waken_discord-0.1.0.tar.gz.
File metadata
- Download URL: waken_discord-0.1.0.tar.gz
- Upload date:
- Size: 10.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13dc275e4fcdf1f9245ff412027d4698d9b95daacb238e253d7a51338aecfed4
|
|
| MD5 |
6f2df835b24b54ce0f2a0f95f76f8f5e
|
|
| BLAKE2b-256 |
79134494c8d4d4d917500dd7a4ab4fd613a702fbf273ac47d8313313d018beb2
|
Provenance
The following attestation bundles were made for waken_discord-0.1.0.tar.gz:
Publisher:
publish.yml on WakenHQ/waken-discord
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waken_discord-0.1.0.tar.gz -
Subject digest:
13dc275e4fcdf1f9245ff412027d4698d9b95daacb238e253d7a51338aecfed4 - Sigstore transparency entry: 2082077031
- Sigstore integration time:
-
Permalink:
WakenHQ/waken-discord@4f52c53bee8f44d87a277b4d1c0eb9040a45b02c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/WakenHQ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4f52c53bee8f44d87a277b4d1c0eb9040a45b02c -
Trigger Event:
push
-
Statement type:
File details
Details for the file waken_discord-0.1.0-py3-none-any.whl.
File metadata
- Download URL: waken_discord-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec6b795bdda11cc85f5acb343d1a9adfd07d71a14b30ffc59267213e707578c8
|
|
| MD5 |
8bc45f5776a900a9b26eb6dde9287af3
|
|
| BLAKE2b-256 |
a5f0c968a3c89cb378d61b9c371da524466abc3cfebbcbc47002f45207e457eb
|
Provenance
The following attestation bundles were made for waken_discord-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on WakenHQ/waken-discord
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waken_discord-0.1.0-py3-none-any.whl -
Subject digest:
ec6b795bdda11cc85f5acb343d1a9adfd07d71a14b30ffc59267213e707578c8 - Sigstore transparency entry: 2082077039
- Sigstore integration time:
-
Permalink:
WakenHQ/waken-discord@4f52c53bee8f44d87a277b4d1c0eb9040a45b02c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/WakenHQ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4f52c53bee8f44d87a277b4d1c0eb9040a45b02c -
Trigger Event:
push
-
Statement type: