gateway
kolega-code gateway
Section titled “kolega-code gateway”The messaging gateway runs a long-lived daemon that connects Kolega Code to a chat platform, so you can drive your agent from your phone. Today it ships a Telegram adapter (official Bot API via @BotFather); the adapter layer is designed for more platforms later.
Each chat gets its own durable Kolega session. Turns stream into the chat as
edit-in-place messages, permission approvals and ask_user_choice questions
arrive as inline buttons, and voice notes, images, and documents are handled
(the local voice-transcription provider needs the stt extra).
-
Create a bot with @BotFather and copy its token.
-
Save it and explicitly authorize your numeric Telegram user ID — either from the CLI (replace the example ID with your own):
Terminal window kolega-code gateway telegram setup --verify --allow '123456789'or from the TUI: Settings → Gateway (bot token, allowed users, pairing, permission mode, adapter, and project; voice transcription lives under Settings → Tools). Everything is stored in
settings.jsonlike every other key — see Gateway settings. -
Run it:
Terminal window kolega-code gateway run --project ~/kolega-code-workspace
Without --project/gateway.project, sessions work in
~/kolega-code-workspace — never the daemon’s launch directory. Message the
bot from your phone; unknown senders are dropped (or get a pairing code, see
Pairing the first or another sender).
--allow '123456789,987654321' authorizes multiple users. Use numeric IDs, not
@handles, display names, or *. The bot token authenticates the bot to
Telegram; it does not authorize a person to use your agent.
Token-only setup, including piped input, is a successful configuration save,
not proof that anyone can use the bot. When no operators are authorized, setup
warns that access is locked (or pairing-only if already enabled) and explains
how to supply --allow or enable pairing in Settings → Gateway. Setup never
enables pairing implicitly.
- Omitting
--allowpreserves the existing configured IDs. - Explicit
--allow ''clears onlygateway.allowed_users. It does not revoke users previously approved through pairing. - Settings-based access changes require a gateway restart; saving settings does not automatically restart the service.
Commands
Section titled “Commands”| Command | Description |
|---|---|
run |
Run the gateway in the foreground (graceful stop on Ctrl-C/SIGTERM). |
status |
Show daemon/service health, heartbeat freshness, and the running daemon’s effective access policy. |
telegram setup |
Save the @BotFather token (with optional --verify, --allow <ids>, --clear). |
pairing list / pairing approve <code> |
List pending sender pairing requests, or admit a sender. |
install / uninstall / restart |
Install, remove, or restart the gateway as a user-level background service (systemd user unit / launchd agent — no root needed). |
run options: --adapter echo|telegram, --project, --state-dir,
--provider, --model.
Running kolega-code update automatically restarts the gateway service if it is installed, so the running daemon picks up new versions immediately.
For other upgrade methods or a foreground daemon, explicitly restart the
process. Updating files on disk does not harden an old process still running.
The background service launches through your login shell ($SHELL), so the
daemon sees the same environment as an interactive terminal — service
managers alone provide a minimal PATH that would hide user-installed tools
from gateway-driven sessions. Restart the service after changing your shell
profile to pick up the new environment.
Running access policy
Section titled “Running access policy”Startup and kolega-code gateway status report the enforced policy, configured
user count, valid paired-user count, and whether pairing is enabled. Status
uses the running daemon’s heartbeat, not newly edited settings, to describe
what that process enforces:
| Policy | Meaning |
|---|---|
locked |
No configured or valid paired users, and pairing is disabled. Remote messages cannot use the agent. |
pairing-only |
No authorized users yet; unknown senders can request a code, but cannot use the agent until locally approved. |
restricted |
Only configured or valid paired users are authorized; group restrictions still apply. |
A locked daemon can remain running and warns at startup when onboarding is disabled. Older heartbeats without access fields show access policy unknown; restart/update to verify — they are not evidence of safe enforcement. Local echo is identified separately from remote access.
In-chat commands
Section titled “In-chat commands”/new, /status, /model [model], /permissions [ask|auto], /stop, /help.
The same commands are registered with Telegram so they appear in the slash
menu while typing.
Access rules
Section titled “Access rules”Remote access is deny-by-default. Authorized sender IDs are the union of
gateway.allowed_users in settings.json and valid approvals in
gateway_allowlist.json, both in the gateway’s state directory. An empty
configured list means paired users only; if neither source authorizes anyone,
the gateway is locked with pairing off or onboarding-only with pairing on.
There is no implicit public mode, wildcard, or first-message-wins admission.
Unknown senders cannot create or resume sessions, run slash commands, approve tools, change permissions, or trigger attachment downloads, file writes, or transcription. Enabling pairing permits only the onboarding reply, not agent access. Rejected permission-button taps do not consume the legitimate pending prompt and do not generate pairing replies.
Group admission also requires an authorized sender. gateway.group_ids and
mention gating restrict where the bot responds; neither grants permission to
otherwise unauthorized group members.
Pairing the first or another sender
Section titled “Pairing the first or another sender”Pairing can onboard the first user, with no configured IDs. It is disabled by default and always requires approval from the local machine:
-
Save the bot token, then enable pairing in Settings → Gateway and apply the change. You may leave allowed users empty.
-
Start the gateway, or restart it if it was already running, so it loads
gateway.pairing_enabled: true. -
From the intended Telegram account, DM the bot to receive a pairing code. This does not create an agent session or grant access.
-
On the local machine, using the same state directory as the daemon, run:
Terminal window kolega-code gateway pairing listReview the code, numeric sender ID, display name, channel, and chat. Confirm the code with the intended person through a trusted channel. Display names alone are not proof of identity.
-
Approve only that confirmed request locally:
Terminal window kolega-code gateway pairing approve <code> -
DM the bot again. Persisted approvals are reread dynamically, so the approved user’s next message is admitted without restarting the daemon.
Codes expire after one hour by default (gateway.pairing_code_ttl_seconds).
Other unknown senders remain unauthorized. Disabling pairing stops onboarding,
but does not revoke existing approvals.
Upgrade and exclusive-owner lockdown
Section titled “Upgrade and exclusive-owner lockdown”Intentional security change: old deployments that relied on an empty list to admit everyone become locked or pairing-only after restarting with the updated code, unless valid persisted approvals already authorize users. Restart any old daemon; an upgrade on disk alone is insufficient. No existing sessions or approvals are automatically deleted.
To restrict a deployment to one owner:
- Stop the gateway before editing access data. For a foreground run, use
Ctrl-C. For an installed service,
kolega-code gateway uninstallstops and removes the service registration without deleting settings or approvals; checkgateway statusto confirm it is no longer running. - Inspect both
settings.json→gateway.allowed_usersandgateway_allowlist.jsonin that daemon’s state directory. Remove unwanted approval records and set the configured list to only the owner’s quoted numeric ID, such as["123456789"]. Setgateway.pairing_enabledtofalseif no further onboarding is wanted. Preserve unrelated settings, tokens, credentials, and any intended approval records. - Restart the foreground run, or use
kolega-code gateway installto restore and start the service removed in step 1. Checkgateway statusfor the running policy and counts.
Clearing only one authorization source does not clear the other. In particular,
telegram setup --allow '' does not revoke persisted approvals, and removing
approvals does not revoke configured users. Removing the final authorization
locks access rather than opening it.
Repairing malformed access settings
Section titled “Repairing malformed access settings”Malformed security settings fail with an actionable error naming the field and
expected form; they are not silently discarded or replaced with permissive
defaults. Repair the identified field in settings.json — do not delete the
settings file or credentials:
gatewaymust be a JSON object when present.gateway.allowed_usersandgateway.group_idsmust be lists of nonempty strings. For Telegram, use positive ASCII-decimal user IDs and signed nonzero ASCII-decimal group IDs, for example["123456789"]and["-1001234567890"]. JSON numbers, booleans, scalar strings, blank entries, handles, and wildcards are invalid.gateway.pairing_enabledmust be the JSON booleantrueorfalse, not a string such as"false".
Missing keys and empty lists are valid safe settings; surrounding ID whitespace is trimmed and duplicates are removed. Invalid CLI/TUI input is rejected before saving, including before replacing a token. After repairing settings, restart the gateway to load the correction.
Voice transcription
Section titled “Voice transcription”Voice notes transcribe remotely through Groq’s hosted whisper-large-v3-turbo
(the same provider/model Hermes uses), configured in the settings TUI under
Tools → Voice transcription. stt_enabled, stt_provider, and stt_model
live at the top level of settings.json; the provider reuses the Groq API key
stored on the Providers page (or GROQ_API_KEY in the gateway’s environment).
Audio is uploaded to Groq’s transcription endpoint for the request and never
stored. Transcription is remote-only — there is no local whisper backend.
- Groups are mention-gated (
@yourbot) and optionally restricted togateway.group_ids. - The echo adapter (
--adapter echo) drives the full transport pipeline over stdin/stdout without any LLM or Telegram account — handy for testing. Only the actual local echo adapter’s standardownersender is admitted without an explicit configured allowlist; explicit lists retain their restrictions and custom echo sender IDs must be authorized. This local console allowance never applies to Telegram or arbitrary adapters. - The Telegram connection uses the official Bot API with a BotFather token, never a personal user account.