Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions docs/telegram-adapter-functional-analysis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Telegram adapter: functional analysis and migration acceptance criteria

- Status: proposed
- Technical workstream: CH-TG (Telegram compatibility adapter)
- Functional owner: Agis (Agent communications and platform agents)
- Operational delivery: Agda; contract ratification: Calluna and Agoga

`CH-TG` is a technical-workstream identifier, not a platform module number.
Canonical `M1`–`M9` identifiers remain reserved by
`hyperdev-infra/docs/TEAM-RULES.md`; agent communications have no separate
canonical `M<n>` identifier.
- System contract authority: [HyperDev unified channels contracts](https://github.com/gohyperdev/hyperdev-platform/blob/main/docs/architecture/unified-channels-contracts-and-delivery-plan.md)
- Decision record: [ADR-076](https://github.com/gohyperdev/hyperdev-platform/blob/main/docs/adr/ADR-076-unified-channels-edge.md)
- Runtime dependency: `hyperdev-channels` host runtime and Claude Code bridge

## 1. Purpose and non-goals

`hdcd-telegram` is the compatibility reference implementation for the Telegram
channel while HyperDev moves routing and configuration onto the platform. Its
current 0.2 router mode already provides a valuable migration primitive: one
Telegram poll owner, many Claude Code sessions and filesystem mailboxes.

The target state is different:

- the platform `channels-edge` owns the Telegram token reference, update offset,
provider authentication, access policy, conversation route and outbound API
delivery;
- the platform-managed host worker owns agent registration, mailbox receive and
session lease;
- Claude Code sees one generic `channels` MCP bridge, not a separate Telegram
MCP server;
- only agents with an explicit Telegram ChannelInstance are exposed through a
bot. The initial scope is Agda and Calluna.

This repository does not become the source of tenant routing, agent discovery,
Teams support or provider-independent MCP lifecycle.

## 2. Current capability inventory

| Capability | Current `hdcd-telegram` | Target owner |
| --- | --- | --- |
| Bot API polling and single poller | standalone and `hdcd-router` | channels edge |
| Multi-session assignment | router topics + mailbox files | host worker session lease |
| Pairing and allowlist | local state | platform policy with migration import |
| Text, Markdown and chunked reply | local tool | Telegram adapter |
| Threads/forum topics | local tool/router | Telegram adapter + conversation route |
| Attachments/download | local tool | adapter/media policy |
| Reactions and edits | local tools | adapter capability operations |
| Permission relay | local inline keyboard | bridge/adapter extension path |
| Voice transcription | local Whisper path | explicit design decision: worker or media service |

The existing direct binary remains a rollback path during migration. It must
not run concurrently with a platform poller for the same production token:
Telegram permits one `getUpdates` owner, otherwise updates conflict.

## 3. Adapter contract binding

The Telegram adapter implements provider contract C6. It consumes a verified
ChannelInstance and produces a source-neutral `CommunicationEnvelope`.

### Inbound mapping

```ts
type TelegramInboundMapping = {
provider: 'telegram';
channelInstanceId: string;
providerUpdateId: string;
providerConversationRef: string;
senderRef: string;
text: string;
replyRef?: string;
attachmentRefs?: string[];
};
```

The adapter verifies bot/update provenance, deduplicates by update/message
identity, applies the configured access policy and asks the platform to bind
the verified channel instance to a tenant and target agent. Provider payload
cannot select an arbitrary tenant or agent.

### Outbound mapping

```ts
type TelegramDeliveryCommand = {
routeRef: string; // opaque platform conversation/contact route
operation: 'reply' | 'send' | 'react' | 'edit' | 'download';
idempotencyKey: string;
payload: unknown;
};
```

The adapter accepts only a CH-EDGE-issued route reference. A model, local worker or
Telegram user cannot supply a raw `chat_id` as an authoritative delivery target.

## 4. Functional analysis

### FA-TG-01: single-poller safety

**Actor:** Telegram adapter deployment.

**Behaviour:** acquire the configured bot token lease before polling; persist
the update offset; reject a second owner; release/expire the lease during
controlled cutover.

**Acceptance:** the same production bot cannot be polled by legacy and platform
implementations at once. Shadow testing uses a distinct test bot.

### FA-TG-02: inbound acceptance and pairing policy

**Actor:** Telegram sender and channels edge.

**Behaviour:** evaluate migrated pairing/allowlist policy before creating a
platform conversation/envelope; return the agreed pairing response where
required; store provider references tenant-scoped.

**Acceptance:** unpaired sender cannot inject an envelope; a paired sender
cannot reach another tenant/agent; legacy access-state import is auditable and
reversible.

### FA-TG-03: conversational reply and initiated send

**Actor:** Claude Code agent.

**Behaviour:** `reply` uses an opaque context; initiated `send` resolves only
an authorised contact/conversation alias. Telegram constraints remain visible:
the bot can start a message only where it already has an allowed chat route.

**Acceptance:** threading follows the original message when appropriate;
unknown/raw chat targets are rejected; duplicate tool retries do not duplicate
an outbound Telegram message.

### FA-TG-04: media and rich operations

**Actor:** adapter and bridge.

**Behaviour:** advertise operations only when the route/capability permits
them; process attachments through a tenant-scoped media policy; retain reaction,
edit and permission-relay semantics that are approved for the pilot.

**Acceptance:** the feature-parity matrix below is tested for Agda and Calluna.
Voice transcription has an explicit owner before migration, rather than an
implicit loss of functionality.

## 5. Definition of Ready

- C4-C6 platform contracts are merged and fixture-backed.
- Telegram ChannelInstance schema, secret reference and access-policy ownership
are implemented by the platform workstream.
- Feature-parity scope for Agda and Calluna is signed off.
- A test bot is available for integration testing; a production cutover owner
and rollback procedure are named.
- Voice transcription disposition is decided: host worker capability or
platform media service.

## 6. Definition of Done

- platform adapter passes the approved text, thread, attachment, reaction,
edit, pairing and permission-relay matrix;
- one production token has exactly one poll owner;
- bot secret is absent from Claude Code MCP config, process arguments and logs;
- Agda, then Calluna, use the generic `channels` MCP bridge rather than a
separate Telegram MCP entry;
- agents without an enabled Telegram ChannelInstance have no Telegram route;
- rollback to the direct compatibility binary is documented and tested before
each production-token cutover.

## 7. PR breakdown and integration plan

| PR | Scope | Dependency | Acceptance |
| --- | --- | --- | --- |
| T1 | Telegram adapter contract fixtures and parity matrix | C4-C6 | mappings and errors are deterministic, no provider secret in fixture output |
| T2 | Compatibility bridge integration | CH-HOST/CH-MCP | one generic bridge can consume Telegram envelopes through test mailbox IPC |
| T3 | Platform adapter ingress/outbound | CH-EDGE | token lease, offset, dedupe and route-bound delivery pass integration tests |
| T4 | Agda pilot | T1-T3 | test bot then controlled production cutover with rollback evidence |
| T5 | Calluna pilot | T4 | same criteria on a second agent without cross-agent state leakage |

Pre-production rollout uses the single platform runtime in controlled sequence:

1. run fixtures and test-bot integration with T1-T3;
2. enable only Agda's test ChannelInstance;
3. stop legacy poller, enable platform poller and verify Agda production bot;
4. retain a time-bounded rollback window;
5. repeat for Calluna;
6. remove direct Telegram MCP configuration only after both pilots pass.

## 8. Evidence required at each pilot gate

- adapter version and configured ChannelInstance ID;
- token-poll owner and offset health, without token disclosure;
- inbound dedupe and outbound idempotency evidence;
- pairing/access positive and negative tests;
- reply, initiated send and attachment operation results;
- platform delivery/lease dashboard state;
- exact rollback command and named operator.
Loading