Replace TGEX with Call Baxter¶
Call Baxter v0.8.0 includes a TGEX/telegras2 compatibility mode. It preserves the operational contracts used by a running TGEX deployment while executing the Call Baxter runtime, Telegram projection package, and WordPress plugin.
The compatibility layer is intended for a low-risk service cutover. It is not a source-level emulation of TGEX internals.
Install the coordinated release¶
Install all four v0.8.0 coordinated Python artifacts into the same environment:
python -m pip install \
call_baxter-0.8.0-py3-none-any.whl \
tg_agent_cli-0.8.0-py3-none-any.whl \
cb_wordpress_plugin-0.8.0-py3-none-any.whl \
cb_social_plugin-0.8.0-py3-none-any.whl
The call-baxter package installs both legacy command names:
Native Call Baxter commands remain available as call-baxter, cb, and call-baxterd.
Compatibility matrix¶
| TGEX surface | Call Baxter replacement | Compatibility notes |
|---|---|---|
telegras2 start |
Same command | Starts the Call Baxter ASGI application. --host, --port, and --reload remain accepted. |
telegras2 polling |
Same command | Uses the telegram.updates poller and the automatic Call Baxter schedule runner. --stop-after-updates is supported for finite/test runs. |
| Deployment validation | telegras2 doctor |
Performs offline checks by default; add --online to verify the Telegram token and webhook state. JSON output is available for automation. |
| Historical TGEX data | telegras2 migrate-history |
Imports interactions, route executions, and handler executions idempotently. --dry-run, --limit, and a separate --source-database are supported. |
| Webhook mode | Same configured path | WEBHOOK_PATH=webhook/{secret} and WEBHOOK_PREFIX are resolved to the old URL path. |
GET /healthz |
Same path | Returns the legacy service-shaped health response. Native health remains available at /v1/health. |
| Introspection API | Same /internal/introspection/* paths |
Authentication and primary operational responses are preserved. Imported TGEX route/handler history is merged with current Call Baxter events/actions. |
| Telegram persistence | tg-agent-cli projection store |
New updates, chats, messages, callbacks, media, actions, polling runs, and webhook snapshots are persisted. |
| Telegram CLI operations | tg CLI and legacy webhook commands |
The dedicated tg CLI is the richer native operator interface. |
| WordPress mirroring | cb-wordpress-plugin |
Supports text/entities, media, media groups, edits, idempotency, post types, default terms/author, filtering, dry-run, retry, and nonfatal media failures. |
| TGEX Python plugins | Call Baxter plugins and YAML rules | The Python plugin ABI is different. PLUGINS/BOT_PLUGINS values are detected and warned about, but not imported. Port custom plugins before final cutover. |
Preserved environment variables¶
The launcher accepts the TGEX names and aliases below.
Runtime and Telegram¶
BOT_TOKEN / TELEGRAM_BOT_TOKEN / TGCLI_BOT_TOKEN
BOT_MODE / MODE
WEBHOOK_SECRET / BOT_WEBHOOK_SECRET / TELEGRAM_WEBHOOK_SECRET
WEBHOOK_PATH / BOT_WEBHOOK_PATH
WEBHOOK_PREFIX
WEBHOOK_URL / BOT_WEBHOOK_URL
TELEGRAM_WEBHOOK_HEADER_SECRET / WEBHOOK_HEADER_SECRET / BOT_WEBHOOK_HEADER_SECRET
PERSISTENCE_ENABLED / BOT_PERSISTENCE_ENABLED
DATABASE_URL / BOT_DATABASE_URL / TGCLI_DATABASE_URL
POLLING_TIMEOUT / BOT_POLLING_TIMEOUT / BOT_POLLING_TIMEOUT_SECONDS
POLLING_IDLE_SLEEP / BOT_POLLING_IDLE_SLEEP / BOT_POLLING_IDLE_SLEEP_SECONDS
POLLING_ERROR_BACKOFF / BOT_POLLING_ERROR_BACKOFF / BOT_POLLING_ERROR_BACKOFF_SECONDS
HOST / BOT_HOST
PORT / BOT_PORT
RELOAD / BOT_RELOAD
LOG_LEVEL / BOT_LOG_LEVEL
INTROSPECTION_ENABLED / BOT_INTROSPECTION_ENABLED
INTROSPECTION_TOKEN / BOT_INTROSPECTION_TOKEN
PLUGINS / BOT_PLUGINS
WordPress bridge¶
WORDPRESS_BRIDGE_ENABLED
WP_BASE_URL
WP_USERNAME
WP_APP_PASSWORD
WP_POST_TYPE
WP_POST_STATUS / WP_PUBLISH_STATUS
WP_CATEGORIES
WP_TAGS
WP_DEFAULT_AUTHOR
WP_DRY_RUN
WP_USE_FEATURED_MEDIA
WP_REQUIRED_HASHTAG / REQUIRED_HASHTAG
TG_ALLOWED_CHAT_IDS / WP_ALLOWED_CHAT_IDS
TG_ALLOWED_CHANNEL_USERNAMES / WP_ALLOWED_CHANNELS
TG_REQUIRE_CHANNEL_POST / WP_REQUIRE_CHANNEL_POST
TG_MEDIA_RETRY_ATTEMPTS
TG_MEDIA_RETRY_BACKOFF_SECONDS
TG_MEDIA_GROUP_WAIT_TIMEOUT_SECONDS
Call Baxter also recognizes TELEGRAM_API_BASE, TG_MEDIA_STORAGE_MODE, TG_MEDIA_BASE_DIR, and BRIDGE_DOWNLOAD_DIR for the replacement projection/media paths.
Generated compatibility state¶
By default, compatibility mode writes its generated runtime configuration beneath:
./data/call-baxter-tgex/
├── call-baxter-tgex.yml
├── call-baxter.db
├── rules.d/
├── media/
└── wp-publications.db
Override the directory with CALL_BAXTER_TGEX_STATE_DIR.
The generated YAML contains resolved credentials and is created with mode 0600. Keep the state directory private and out of source control.
The Telegram projection database continues to use DATABASE_URL. TGEX compatibility currently supports SQLite database URLs and filesystem paths only. sqlite+aiosqlite:///... and sqlite:///... are converted to their underlying file path.
The projection audit tables are named tg_route_executions and
tg_handler_executions. This avoids a schema collision with TGEX's different
tables named route_executions and handler_executions. A schema-version-2
migration renames only older tg-agent-cli tables whose columns positively
identify them; genuine TGEX tables remain untouched for historical import.
Cutover procedure¶
1. Back up the running service¶
Also capture the active Telegram webhook before changing the process:
2. Stop TGEX and install v0.8.0¶
Stop the old process without deleting its database or media directories, then install the four coordinated wheels.
3. Validate environment translation¶
Initialize the replacement stores and generated configuration:
Run the deployment doctor before starting the replacement process:
The offline doctor validates local configuration without contacting Telegram.
The online mode additionally calls getMe and getWebhookInfo.
Preview and import historical TGEX records:
The importer is idempotent. It records source-to-target mappings in
tg_legacy_imports, skips rows already migrated, links interactions already
present by Telegram update ID, and imports media metadata without downloading
historical files.
Inspect generated rules without contacting Telegram:
When WordPress is enabled, verify WP_DRY_RUN=true first. This exercises normalization, filtering, and post preparation without making WordPress requests.
4. Start in the existing mode¶
Webhook deployment:
Polling deployment:
The Call Baxter daemon now executes enabled schedules automatically, so the Telegram polling and media-group flush schedules do not require a separate cron or /run-due caller.
5. Verify old and native endpoints¶
curl --fail http://127.0.0.1:8000/healthz
curl --fail http://127.0.0.1:8000/v1/health
curl --fail \
-H "Authorization: Bearer ${INTROSPECTION_TOKEN}" \
http://127.0.0.1:8000/internal/introspection/interactions
The native operator UI is available at /ui. The legacy introspection UI path redirects there.
For an additional webhook authenticity layer, configure
TELEGRAM_WEBHOOK_HEADER_SECRET. The compatibility endpoint then requires a
matching X-Telegram-Bot-Api-Secret-Token header, and telegras2 set-webhook
passes the same secret token to Telegram.
6. Verify Telegram delivery¶
For webhook mode, send one test update through the existing webhook path and confirm it appears in both:
For polling mode, a finite smoke run is available:
7. Enable WordPress writes¶
Set WP_DRY_RUN=false, restart the process, and publish a controlled Telegram message. Confirm:
- the expected post type and status;
- configured categories, tags, and author;
- media behavior according to
WP_USE_FEATURED_MEDIA; - edits update the existing post;
- duplicate deliveries do not create duplicate posts;
- media-group fragments produce one post after the configured wait period;
- a failed Telegram media download is recorded in
media_errorswhile the text post still succeeds.
Historical data migration¶
telegras2 migrate-history imports the TGEX tables below when their expected
columns are detected:
telegram_interactions -> tg_updates, tg_chats, tg_users, tg_messages, ...
route_executions -> tg_route_executions
handler_executions -> tg_handler_executions
Original TGEX tables are never dropped or rewritten. Timestamps, statuses, errors, sources, matched routes, handler results, and durations are retained. The compatibility introspection routes merge imported audit history with new Call Baxter runtime activity.
Keep the pre-cutover backup even after a successful migration. The importer normalizes Telegram payloads into the new browse-oriented schema, so it is not a byte-for-byte database conversion.
Introspection differences¶
The following paths are retained:
GET /internal/introspection/config
GET /internal/introspection/webhook/status
DELETE /internal/introspection/webhook
GET /internal/introspection/ui
GET /internal/introspection/interactions
GET /internal/introspection/interactions/{id}
GET /internal/introspection/route-executions
GET /internal/introspection/route-executions/{id}
GET /internal/introspection/handlers/stats
GET /internal/introspection/chats
GET /internal/introspection/chats/{chat_id}/history
Interaction and chat endpoints are backed by the Telegram projection database. Route execution and handler statistics endpoints combine imported TGEX audit rows with current Call Baxter events/actions. Imported executions retain their positive projection IDs; current runtime events use negative compatibility IDs to avoid collisions. TGEX-specific fields that were never persisted cannot be reconstructed.
Custom plugin migration¶
A TGEX plugin configured through PLUGINS or BOT_PLUGINS cannot be loaded safely into Call Baxter because registration, route matching, dependency injection, and persistence hooks differ.
Port each custom plugin as one or both of:
- a Call Baxter plugin that registers event, ingress, poller, or action definitions;
- YAML rules that connect existing Telegram events to actions.
Do not remove the TGEX process permanently until every configured custom plugin has either been ported or explicitly retired.
Rollback¶
- Stop the Call Baxter compatibility process.
- Restore the old environment and original TGEX executable/image.
- Restore the pre-cutover database if the old application must see an exact filesystem snapshot.
- Restore the prior webhook URL only when it changed.
- Start TGEX and confirm
GET /healthzplus one test update.
The generated CALL_BAXTER_TGEX_STATE_DIR can remain for diagnosis; TGEX does not use it.
Move to native Call Baxter configuration¶
After compatibility mode is stable, migrate intentionally to native configuration:
- replace
telegras2 startwithcall-baxterd --config-file ...; - move generated plugin configuration into an operator-owned YAML file;
- move generated rules into the project rules directory;
- use
/v1/*,/ui, and thetgCLI as the primary operator surfaces; - remove legacy environment aliases and introspection clients only after consumers have moved.
This second step is optional. Compatibility mode is a supported deployment surface for the v0.8.0 release.