# `vita.telegram` capabilities

> GENERATED from the capability registry — do not edit by hand.
> Regenerate with `./run gen-capabilities`. Call any capability:
> `POST /api/v1/capabilities/call/<name>` (body = input JSON) or
> `./run capabilities call <name> --input '<json>'`.

## `vita.telegram.deregister_participant`

**WRITE** · source: data/proactive/queue.db (topic_participants)

Release a topic's active participant claim (no-op if none).

### Input

| field | type | required | default | description |
|---|---|---|---|---|
| `topic_id` | string | yes |  |  |
| `reason` | string |  | `"deregistered"` | Recorded on the claim row |

### Output (`data`)

| field | type | required | default | description |
|---|---|---|---|---|
| `released` | boolean | yes |  |  |
| `label` | string | null |  |  |  |

### Examples

```json
{
  "topic_id": "12999",
  "reason": "work finished"
}
```


## `vita.telegram.open_topic`

**SEND** · source: scripts/threadctl.py + telegram Bot API

Create a new telegram forum topic. With a seed prompt, dispatches the detached kickoff turn (threadctl `new`); without one, creates a bare topic ready for vita.telegram.send / participant registration.

### Input

| field | type | required | default | description |
|---|---|---|---|---|
| `name` | string | yes |  | Topic display name |
| `seed` | string | null |  |  | Optional complete seed prompt. When given, a detached kickoff turn runs (threadctl `new` semantics) and posts the opening message; when omitted, the topic is created bare (e.g. as a participant console for a running process). |
| `source_topic_id` | string | null |  |  | Topic whose agent (persona + model) the new topic inherits |

### Output (`data`)

| field | type | required | default | description |
|---|---|---|---|---|
| `topic_id` | string | yes |  |  |
| `link` | string | yes |  |  |
| `kickoff_dispatched` | boolean | yes |  |  |

### Examples

```json
{
  "name": "garmin-debug console"
}
```

```json
{
  "name": "Race plan",
  "seed": "You are picking up the race-planning thread. Pull ...",
  "source_topic_id": "12930"
}
```


## `vita.telegram.poll_replies`

**WRITE** · source: data/proactive/queue.db (participant_inbox)

Pull buffered bio-zack replies for a mailbox-mode participant claim. Polling refreshes the heartbeat that keeps the claim alive — poll at least every ~40 minutes or the claim auto-releases.

### Input

| field | type | required | default | description |
|---|---|---|---|---|
| `topic_id` | string | yes |  |  |
| `consume` | boolean |  | `true` | False = peek without consuming |

### Output (`data`)

| field | type | required | default | description |
|---|---|---|---|---|
| `participant_id` | integer | yes |  |  |
| `label` | string | yes |  |  |
| `expires_at` | string | yes |  |  |
| `replies` | ParticipantReply[] |  |  |  |

### Examples

```json
{
  "topic_id": "12999"
}
```


## `vita.telegram.register_participant`

**WRITE** · source: data/proactive/queue.db (topic_participants)

Register as a topic's LIVE PARTICIPANT for N hours: bio-zack's replies in that topic route into YOUR process (mailbox pull) or YOUR inference session (auto-resume). Exclusive claim; resident session catches up from the topic ledger when the claim ends.

### Input

| field | type | required | default | description |
|---|---|---|---|---|
| `topic_id` | string | yes |  | Topic to claim (must be a real topic id) |
| `label` | string | yes |  | Who/what is registering, e.g. 'finish-line session' |
| `mode` | string | yes |  | mailbox = replies buffer for pull via vita.telegram.poll_replies (polling is the heartbeat; ~45min silence auto-releases). session = replies resume the given inference session_key and its response posts back to the topic. |
| `ttl_hours` | number |  | `4.0` | Claim lifetime; auto-releases at expiry |
| `session_key` | string | null |  |  | Required for mode=session |

### Output (`data`)

| field | type | required | default | description |
|---|---|---|---|---|
| `participant_id` | integer | yes |  |  |
| `expires_at` | string | yes |  |  |
| `mode` | string | yes |  |  |
| `note` | string |  | `"EXCLUSIVE claim: while active, bio-zack's plain messages in this topic route to the participant, not the resident session. 'release' in-topic or vita.telegram.deregister_participant ends it early."` |  |

### Examples

```json
{
  "topic_id": "12999",
  "label": "garmin-debug session",
  "mode": "mailbox",
  "ttl_hours": 2
}
```

```json
{
  "topic_id": "12999",
  "label": "race-planner",
  "mode": "session",
  "session_key": "bg-12999-1234"
}
```


## `vita.telegram.send`

**SEND** · source: telegram Bot API (direct) + data/telegram/topic_ledger.jsonl

Post a message into a telegram topic NOW (direct Bot API, synchronous). The send records into the topic ledger so the topic session sees it on its next turn — the funnel-everywhere invariant, enforced. Returns the telegram message id or a structured error; drops are impossible to miss.

### Input

| field | type | required | default | description |
|---|---|---|---|---|
| `text` | string | yes |  | Message text (telegram rich HTML allowed) |
| `topic_id` | string |  | `"0"` | Telegram topic ('0' = General) |
| `trigger` | string |  | `"capability_send"` | Label recorded in the topic ledger + conversation log |
| `disable_notification` | boolean |  | `false` | Send silently (no client ping) |

### Output (`data`)

| field | type | required | default | description |
|---|---|---|---|---|
| `telegram_msg_id` | integer | yes |  |  |
| `topic_id` | string | yes |  |  |
| `ledger_recorded` | boolean | yes |  | True = the topic session will see this message on its next turn |

### Examples

```json
{
  "text": "heads up \u2014 the garmin sync just recovered",
  "topic_id": "0"
}
```

```json
{
  "text": "progress: 3/5 lanes done",
  "topic_id": "12930",
  "trigger": "participant_update"
}
```

