DEV Community

Cover image for Unknown Telegram Senders Should Stay Guests in APX

Unknown Telegram Senders Should Stay Guests in APX

Unknown Telegram Senders Should Stay Guests in APX

A Telegram bot should not treat every new message as trusted operator input.

That sounds obvious, but a lot of agent setups still blur identity, chat membership, and tool access. Someone writes to a bot, the bot answers, and before long the same person can trigger real actions because the runtime never drew a hard line between conversation and capability.

APX draws that line on purpose.

APC is the portable context layer. It keeps the project contract in the repo: AGENTS.md, .apc/, agent definitions, skills, commands, and MCP hints. APX is the daily-use runtime and tooling layer. It reads that project context, runs the agent loop, and handles runtime state such as sessions, messages, approvals, and channel identity outside the repository.

That trust decision belongs to APX, not APC.

Guest first, tools later

The APX Telegram identity logic is explicit.

A contact is keyed by the sender's stable Telegram user_id, not by chat_id. That matters because the same person may appear across different chats, while group chats can contain many people. APX stores the person globally and only uses owner_user_id to mark who owns one specific channel.

Then it applies a simple rule:

  • channel owner gets owner
  • configured contacts can get a custom role
  • unknown senders become guest

That last step is the important one.

In resolveAllowedTools(), APX gives the owner "*", reads tool allowlists from telegram.roles for known roles, and otherwise returns an empty list. In other words, guests fail closed. They can talk to the bot, but they do not get tool power just because they found the chat.

That is a better default than optimistic trust.

Why this split matters

A Telegram conversation has two separate questions:

  1. who is this person?
  2. what may this person trigger?

If a runtime collapses those into one step, it tends to over-grant. "Known enough to answer" quietly becomes "known enough to act."

APX does not do that.

The relationship block that feeds the model prompt is also strict. For a guest sender, APX tells the model it is talking to a guest with no permissions and instructs it to ask politely who they are. That keeps the social flow natural without pretending the model can grant access on its own.

So there are really three layers working together:

  • runtime identity resolution
  • prompt context about that identity
  • tool allowlist enforcement

That combination is what makes the behavior safe instead of merely friendly.

Small example

Imagine a fresh project bot pinned to one APX project.

The first private message on an owner-less channel can claim ownership. After that, another sender writing to the same bot is not promoted just because the conversation is private. APX records that person as a guest.

If you later want that contact to do more, you assign a role in APX config or through the web admin, where each role maps to a concrete tool list such as call_agent or list_tasks.

That means the trust upgrade is deliberate and reviewable.

Notably, APX does not grant power because a username looks familiar, because a user joined the chat, or because the model decided the person "seems legit." The runtime owns the permission boundary.

Why APC should stay out of it

This is not durable project context. It is live runtime policy.

APC should describe the project, its agents, its skills, and other repo-owned context that can travel across machines and runtimes. It should not commit transient channel trust or personal messaging access into the project contract.

Telegram roles, ownership claims, and sender registration depend on who is operating the bot right now. That is machine-local, runtime-managed state. APX is the right home for it.

This boundary is easy to miss, but it matters.

If APC stored this kind of messaging trust directly, portability would get worse and accidental exposure would get easier. By keeping APC portable and APX responsible for channel identity, the project contract stays clean while the runtime stays cautious.

That is the real design point: APC says what the project means. APX decides who, through Telegram, gets to do anything with it.

Top comments (0)