pairing — connecting users, channels, and devicesAsk Metnos with a request like this example: “Show me how to connect Telegram to the user Lucia.” The Tutor gives the path in the web chat even when the question comes from Telegram.
In Metnos, pairing establishes a verified identity before a request is processed. Identity is never inferred from message text. A logical user, a channel address, a chat session, and an execution device are distinct objects with independent registries and revocation paths.
| Object | What it identifies | Current source |
|---|---|---|
| Logical user | The person who owns a role, preferences, language, and channels. | users.db, users table |
| Channel | A verified address, such as a Telegram chat_id or a paired browser. | users.db, user_channels table; Telegram also uses pairings.db |
| Chat session | The device that currently has write access to the user's web conversation. | users.db, active_sessions and chat_conversations tables |
| Remote device | A machine authorised to run executors for a specified owner. | devices.db, devices table |
A paired browser is not automatically a remote device. The former provides chat access; the latter receives work from the server and runs it on the machine where the relevant data or applications live. Likewise, transferring a web session does not alter Telegram pairing or device ownership.
runtime/users.py maintains one host user and any
number of guest users. Each record has a technical identifier, a
unique name, a role, an optional owner, and an autonomy level.
user_channels links that same user to verified
telegram, mail, and http channels.
Language and preferences are resolved from the authenticated binding before the turn and applied in a request-local context. A change for one user does not change another user's language or session. Conversations, pending dialogs, and web-chat write authority are also scoped by user and channel.
The two registries use different vocabularies and they are not interchangeable:
users.db: read_only, restricted, full;pairings.db: ReadOnly, Supervised, Full.In the Telegram daemon, ReadOnly prevents an operational turn
from starting. Supervised and Full can enter the
runtime; every executor remains subject to its manifest, safety controls, and
required approvals. A stored level is not, by itself, proof that a particular
action is authorised.
From the web chat, open Settings > System > Users. Create or select the user, then use the pairing control for the required channel. If you are reading these instructions in Telegram, this path is in the Metnos web chat, not in the Telegram application.
/start <token>.chat_id to the user, and confirms the pairing.The token is random, one-time, and valid for one hour. Consumption uses a
SQLite transaction, so two concurrent requests cannot both use the same token.
The /start command performs the pairing but does not run an
operational request; the next message starts a new turn.
HttpOnly, Secure cookie.The user cookie lasts at most 90 days, but on every verification the server checks that the HTTP binding still exists. Removing the channel from the user detail page therefore invalidates access even if the browser retains the cookie.
runtime/pairing.py also provides the technical
/pair PAIR.<payload>.<signature> flow. The payload declares
the version, identifier, autonomy level, expiry, and issuer; its Ed25519
signature is checked against trusted public keys. By default, a code expires
after five minutes and can be consumed only once.
./.venv/bin/python -m runtime.pairing generate <ReadOnly|Supervised|Full> 5m ./.venv/bin/python -m runtime.pairing list ./.venv/bin/python -m runtime.pairing revoke telegram <sender_id>
This flow creates the low-level (channel, sender_id) record.
To connect a person who already exists in the user registry, the
Settings > System > Users flow with /start is
more direct because it preserves the logical identity explicitly.
When bootstrap is enabled, the first message from the
default_chat_id can create a Full pairing only while
the channel has no pairing records. The --no-bootstrap option
instead requires an explicit pairing for the host as well.
Metnos allows one active write session for each
(user, web channel) pair. If you open the chat on one device while
another device holds the session, the window offers three choices:
| Choice | Effect |
|---|---|
| Continue the previous session | Revokes the old device's write authority, transfers its conversation to the current device, and displays its history. |
| Make the current session active | Revokes the old device and keeps the current device's local conversation. |
| Cancel | Changes no session; the current device remains without write authority. |
Resolution is atomic and bound to the authenticated user. The resolution token is one-time, and a user cannot transfer someone else's conversation. When connected, the previous device receives the revocation event and becomes read-only. The conversation belongs to the user, not to the browser.
From the web chat, open Settings > System > Devices. The page lists the name, owner, operating system, client version, key fingerprint, last heartbeat, and state. You can install the client on the current PC, generate a link for a different PC, or issue a manual token.
The guided flow is:
POST /agent/register consumes the token and records the public key, fingerprint, owner, and system characteristics.The guided join session uses a signed, one-time token that normally lasts 30 minutes; the manual variant issued from the page lasts 10 minutes. A second consume with the same key is idempotent, while the same token presented with a different key is rejected. A fresh token paired with the same key is an explicit re-authorisation and can restore a previously revoked device.
The remote-executor protocol uses port 8765 by default on an internal or
private network. Polls, results, and heartbeats are signed by the device over
the exact request bytes. The client verifies server orders and bundles with
the key pinned at pairing time. last_heartbeat shows that the
process is alive; last_poll separately shows that the worker is
requesting work.
| Object | How to revoke it | Effect |
|---|---|---|
| User channel | Remove the channel in Settings > System > Users. | The address no longer resolves to that user; the associated web cookie fails the binding check. |
| Low-level Telegram pairing | ./.venv/bin/python -m runtime.pairing revoke telegram <sender_id> | get_pairing no longer returns the active record. |
| Web session | Explicit sign-out or acquisition from another device. | The write token is marked revoked; the conversation remains owned by the user. |
| Remote device | Use the revoke control in Settings > System > Devices. | Subsequent polls, results, and heartbeats are rejected; the record remains available for audit. |
For the general transport contract, see
channel; for action approvals, see
approvals and human control; for HTTP routes,
see http_api.