Channel Descriptor
Let a channel plugin declare its config, prompt hint, and setup wizard in one place.
A channel plugin declares — in one place — everything the gateway needs to treat it as first-class: its own config keys, a system-prompt hint, an optional setup wizard, and an optional standalone sender.
Quick Start
- Declare a descriptor
List your channel’s config fields and a prompt hint on a small descriptor class:
python from praisonaiagents.bots import ChannelField class IRCDescriptor: config_fields = [ ChannelField("server", required=True, prompt="IRC server host"), ChannelField("nickserv_password", secret=True, env="IRC_NICKSERV_PASSWORD"), ] system_prompt_hint = ( "You are replying on IRC: plain text only, one short line." ) - Register the platform
Pass the descriptor when you register the adapter — the gateway wires config, onboarding, and prompt for you:
python from praisonai.bots._registry import register_platform register_platform("irc", IRCBot, descriptor=IRCDescriptor())
How It Works
One declaration feeds five consumers when the channel is active.
| Consumer | Reads | Effect |
|---|---|---|
| Config schema | config_fields | Plugin keys validate instead of being dropped |
| Onboarding wizard | config_fields (+ optional setup) | Prompts for each field, using env as fallback |
| Agent prompt | system_prompt_hint | Appended to the agent’s backstory and the rebuilt system_prompt at per-channel bot construction |
CLI (bot run) | config_fields | Each field becomes a --field-name flag (underscore → hyphen). Unknown flags exit 2. |
| Scheduler (gateway-less) | standalone_sender (optional) | Scheduled deliver: targets reach the channel when no gateway is resident (OS cron, CI, scale-to-zero) |
CLI flags are generated from config_fields
A channel’s declared config_fields are accepted on praisonai bot run as --field-name flags, so the same declaration drives YAML, the wizard, the agent prompt hint, and the CLI.
# IRC plugin declaring `server` and `nickserv_password`
praisonai bot run --platform irc --server irc.libera.chat --nickserv-password $NICK_PWSee praisonai bot run for syntax and the exit-code-2 error on unknown flags.
How the hint reaches the model
The gateway resolves the descriptor’s hint and appends it to the cloned agent’s backstory, then rebuilds system_prompt — the runtime prompt builder reads those, not the construction-only instructions.
from praisonaiagents.bots import ChannelField
from praisonai.bots._registry import register_platform
class IRCDescriptor:
config_fields = [
ChannelField("server", required=True, prompt="IRC server host"),
]
# This hint now actually reaches the model on every turn.
system_prompt_hint = "You are replying on IRC: plain text only, one short line."
register_platform("irc", IRCBot, descriptor=IRCDescriptor())ChannelField Options
Each ChannelField describes one config key the channel needs.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | — | Config key name (as it appears under channels.<platform>); also the bot run CLI flag (bridge_url → --bridge-url) |
required | bool | False | Whether the field must be provided |
secret | bool | False | Whether the value is sensitive (masked in prompts/logs) |
prompt | str | "" | Human-friendly prompt shown by the onboarding wizard |
env | Optional[str] | None | Environment-variable name used as a fallback source |
Interactive Setup
Add an optional setup(io) hook for multi-step flows that a flat field list can’t express — the wizard calls it when present and merges the returned values.
from praisonaiagents.bots import ChannelField
from praisonai.bots._registry import register_platform
class IRCDescriptor:
config_fields = [
ChannelField("server", required=True, prompt="IRC server host"),
]
system_prompt_hint = "You are replying on IRC: plain text only, one short line."
def setup(self, io) -> dict:
channels = io.prompt("Which channels to join? (comma-separated)")
return {"channels": [c.strip() for c in channels.split(",") if c.strip()]}
register_platform("irc", IRCBot, descriptor=IRCDescriptor())Gateway-less scheduled delivery
Declare an optional standalone_sender and your channel also receives scheduled briefs when no gateway is resident, just like the five bundled channels.
class IRCDescriptor:
config_fields = [
ChannelField("server", required=True, prompt="IRC server host"),
]
system_prompt_hint = "You are replying on IRC: plain text only, one short line."
async def standalone_sender(self, target, text):
await post_to_irc(target.channel_id, text) # raises on failure
class IRCBot:
channel_descriptor = IRCDescriptor() # found by `praisonai schedule tick`
...Best Practices
Mark secrets with secret=True
Set secret=True on tokens and passwords so the wizard masks them and logs never print the value.
Provide an env fallback for secrets
Add env="IRC_NICKSERV_PASSWORD" so operators can supply credentials via environment variables instead of prompts.
Keep the prompt hint short and concrete
State the platform and its constraints in one line — for example plain text only, one short line — so the agent adapts its replies.
Use setup only when fields aren't enough
Reach for setup(io) for bespoke, multi-step flows. Declarative config_fields cover the common case with no code.
Pair standalone_sender with env-backed secrets
The sender runs out of process (OS cron, CI, serverless) and the onboarding wizard never runs there. Give every secret it needs an env= fallback on its ChannelField. See Standalone Sender for Custom Channels.
Pick CLI-friendly field names
Avoid names that clash with fixed bot run flags (token, port, agent, model, platform). A field named like a handler parameter (e.g. an IRC adapter’s channel) is routed through channel.model_extra so it still reaches the adapter, but unambiguous names are clearer for users.
Idempotency & prompt-cache safety
The gateway appends the hint as a single trailing line, so injection is deterministic and the prompt prefix stays cache-stable across turns. A hint already present on the agent’s backstory is a no-op on hot-reload, so re-clones never duplicate it.
Related
Connect agents to Telegram, Slack, Discord, and more
Bot Platform CapabilitiesHow platform capabilities drive channel behaviour
GatewayMulti-agent coordination across channels
PluginsShip channels and tools as pip packages
Channel DirectoryHow an adapter enumerates the channels it can see
Visible-Outcome GuaranteeEvery inbound turn ends in a visible reply or a deliberate silence