Channel Configuration
How channel configuration metadata drives Console UI and runtime persistence
Channel Configuration
Each chat channel (Telegram / Feishu / QQ) exposes a runtime-readable configuration descriptor.
This descriptor directly controls:
- Which fields Console UI renders
- Which fields are editable
- Field types (
string/boolean/number/secret/enum) - Field source (
ship.json)
Why this design
- Remove frontend hardcoding for per-channel fields
- Centralize validation in
chat.configure - Keep clear boundaries:
- Agent service (
ship.json): channel binding + runtime toggles only - Global Channel Accounts (
ship.db): all bot information (token/appId/appSecret/authId/name/owner/creator)
- Agent service (
Agent Service Scope
Agent-side channel config only includes:
enabledchannelAccountId
Only fields with writable=true are editable in Console UI and persisted by chat.configure.
Runtime flow
1. Read status
chat.status returns, per channel:
detail.config: safe config summarydetail.configuration: full configuration descriptor
2. Render UI
Console UI renders forms dynamically from detail.configuration.fields:
- writable fields ->
enabled/channelAccountId
3. Save config
On save, Console UI sends only writable patch fields.
Backend then:
- Filters fields by channel descriptor whitelist
- Normalizes and validates by field type
- Updates in-memory runtime config
- Persists to project
ship.json - Restarts/reloads channel if requested (default: restart)
Relationship with Channel Accounts
Recommended flow:
- Fill credentials in Global Channel Accounts and click
Test - Click
Confirmonly after test passes (bot base info is auto-discovered and saved) - Bind
channelAccountIdin channel configuration - Run
test/reconnect
This cleanly separates secret management and per-agent channel runtime config.
How bot info is fetched
You do not need to manually enter bot name, bot id, or identity.
The system fetches them automatically by channel:
- Telegram:
botToken->getMe - Feishu:
appId + appSecret-> access token -> bot info endpoint - QQ:
appId + appSecret-> gateway validation -> bot profile when available
Console UI keeps the flow minimal and focuses on test status + confirmation.
What you will use
Console UI
- Global -> Channel Accounts: manage global channel accounts
- Channel -> Configuration: bind
channelAccountId, toggleenabled
CLI
Inspect descriptor:
city service command chat configuration --channel qqUpdate and restart:
city service command chat configure \
--channel qq \
--config-json '{"channelAccountId":"qq-main","enabled":true}' \
--restartFAQ
Why no plaintext secrets in channel pages?
By design, channel pages expose safe summaries only.
Why are some fields not editable?
Channel pages handle binding/toggles only. Bot details are managed in Global Channel Accounts.
Why did new fields appear automatically in Console UI?
Because rendering is metadata-driven from detail.configuration, not hardcoded.