The bridge from butschster/bridge to a Telegram channel. Carries articles a person has already approved in the content machine out to subscribers: the bridge picks which one, an agent writes the announcement, and the article itself goes as the markdown it was approved as. The bot is a connection, not an environment variable, so one stand can serve several channels.
Run
wippy run butschster/bridge-telegrambutschster/bridge-telegram
The third bridge, and the second that publishes. It carries articles a person has already approved out to a Telegram channel.
What it declares, and what it deliberately does not
| Capability | State |
|---|---|
| target | getMe with the project's bot — the one call that fails exactly when the token has been revoked |
| publish | names the article, and sends it |
| actors | absent — a channel has no author entity; a bot posts as itself |
| credentials | absent — the bot token is the project's standing credential; nothing is minted per run |
| tools, conversation, oracle | absent — nothing to talk to, no truth to ask for |
The bot is a connection, not an environment variable
butschster/telegram serves one bot, from TELEGRAM_BOT_TOKEN. A stand
that publishes into several channels for several people needs one bot per
project, so the token is read from the connection component the
Connections page already manages and handed to that module's SDK per
call. That is the whole reason its SDK grew an optional token: a
credential belongs to a project, and a registry entry travels into git.
Who chooses the article
Code does, before the agent is briefed — op: subject, answered by the
same capability that will later receive the result. An agent that chose
would choose differently on the next run, so the same piece could go out
twice and the record could not say why. The choice is oldest-first, so a
backlog drains in the order a person approved it.
A run with nothing to send skips; it does not fail. A daily job in a quiet week would otherwise be red every morning, and the scheduler would spend its retries on the one state that is entirely correct.
Why a table rather than a check
Telegram has no idempotency key. A message accepted and a message whose answer was lost look identical from here, so "have we sent this?" asked just before sending is a question whose answer can go stale between the asking and the send. The delivery ledger is keyed on the fact itself — one project, one channel, one article — and the claim is written before anything leaves. A second attempt does not race; it collides.
What goes into the channel
The announcement, written by the agent as plain text, with the link
appended by code — a model asked to reproduce a URL eventually will not.
Then, if the work asks for it, the article itself as the markdown a
person approved: sendDocument, not a rewrite. The one thing this bridge
never does is edit what was approved on the way out.