Route chat channels to agent targets.
Project description
Relayforge
Relayforge routes chat channels to agent targets.
The first provider is Discord. The first targets are a Codex app-server binding and a Codex JSONL fallback inbox. The package is Python and PyPI-ready, with provider-neutral core types so Slack, WhatsApp, and other agent APIs can be added later.
Install
After the package is published:
pip install relayforge
The installed CLI command is relayforge.
Installed wheels add a small managed Relayforge block to:
~/.codex/AGENTS.md~/.claude/CLAUDE.md
Set RELAYFORGE_SKIP_AGENT_GUIDES=1 before starting Python with the installed
package on sys.path to skip this.
From this checkout:
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
Configuration
{
"channels": [
{
"name": "rohan-codex",
"provider": "discord",
"id": "1520170530148192466",
"owner": "rohan"
}
],
"bindings": [
{
"name": "rohan-almanac-main",
"source": "rohan-codex",
"target": "codex-app-server",
"codexThreadId": "replace-with-codex-thread-id",
"cwd": "/Users/rohan/Desktop/Projects/almanac",
"machine": "replace-with-hostname",
"transport": "codex app-server --config mcp_servers={} --listen stdio://"
}
],
"routes": [
{
"channel": "rohan-codex",
"target": "codex-jsonl",
"inboxPath": ".relay/rohan-codex-inbox.jsonl"
}
]
}
Each founder can use the same Discord bot token with a different named channel. A binding delivers to that founder's Codex thread on the right machine. A route keeps JSONL fallback delivery available when the direct target fails.
See docs/channels.md for the multi-founder pattern. See docs/research/codex-thread-routing-2026-06-26.md for the Codex thread binding direction.
Commands
export DISCORD_BOT_TOKEN=...
relayforge init --config relay.config.json
relayforge channels add discord/rohan-codex --id 1520...
relayforge connect discord/rohan-codex --thread-id 019f... --fallback-inbox .relay/rohan-codex-inbox.jsonl
relayforge check --config relay.config.json
relayforge status --config relay.config.json
relayforge listen --config relay.config.json
relayforge reply "I am looking at it now."
relayforge send --channel rohan-codex --message "hello"
relayforge read --channel rohan-codex --limit 10
Raw Discord channel IDs work for read and send even before a config file
exists. Named channels require the config.
The listen command uses Discord Gateway events. That means Discord pushes new
messages to this process instead of the process polling the channel.
connect is the normal agent setup command. It creates a Codex app-server
binding from a provider channel such as discord/rohan-codex to one Codex
thread. When listen receives a message for that binding, Relayforge tries to
steer the active Codex turn first; if the thread is idle, it starts a new turn.
Use these commands when you need the lower-level surface:
relayforge check --config relay.config.json --json
relayforge channels --config relay.config.json
relayforge routes --config relay.config.json
relayforge bindings --config relay.config.json
relayforge channel-set --name rohan-codex --provider discord --id 1520...
relayforge route-set --channel rohan-codex --target codex-jsonl --inbox-path .relay/rohan-codex-inbox.jsonl
relayforge binding-set --name rohan-almanac-main --source rohan-codex --target codex-app-server --codex-thread-id 019f... --cwd /Users/rohan/Desktop/Projects/almanac --transport "codex app-server --config mcp_servers={} --listen stdio://"
relayforge codex-smoke --binding rohan-almanac-main --message "smoke test"
relayforge binding-send --binding rohan-almanac-main --message "reply in Discord"
relayforge inbox --path .relay/rohan-codex-inbox.jsonl --limit 10
relayforge inbox --path .relay/rohan-codex-inbox.jsonl --cursor .relay/rohan.cursor.json --ack
By default, Discord bot-authored messages are ignored to avoid loops. Use
--include-bots only for controlled smoke tests or deliberate bot-to-agent
routing.
codex-smoke sends a synthetic message through a configured Codex app-server
binding. Use it only with a rollout-backed Codex thread that is safe to receive
a test turn.
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 relayforge-0.1.1.tar.gz.
File metadata
- Download URL: relayforge-0.1.1.tar.gz
- Upload date:
- Size: 87.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31b2326c8ecce7c3538f288d4eadeb21971fc21d13a95373ff2bba778ec8542a
|
|
| MD5 |
fbc7a0b8ecffb8b6d2a784047f51ea32
|
|
| BLAKE2b-256 |
28dcb841d8e3dc71788e3dc5ec225258df8f634761fc4f6ccc1a93b325f33efa
|
File details
Details for the file relayforge-0.1.1-py3-none-any.whl.
File metadata
- Download URL: relayforge-0.1.1-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ae5a2ad74acf21002f343b5dfc6214f603d8de552eb20f1c772f63037c9b241
|
|
| MD5 |
8b213b06220fe0bec3cb9b6b950a7226
|
|
| BLAKE2b-256 |
b743c9d70d6fc8f23430c9ffa1c3d90192fc5f16afdcd83d4da60ddbcb1b9f1f
|