# Your agent asks permission on Telegram

Link Telegram once; from then on the agent can ask you, and you answer with a tap.

## 1. Link Telegram

During setup:

```bash
npx brynth init --telegram
```

or later, by asking your agent to call:

```text
channel_add({kind: "telegram", label: "phone"})
```

You get a `t.me` link. Open it and press Start within 10 minutes; the code in the link works once. Brynth then asks the project's active channels (at first, your email) to approve the new channel. The channel is `active` only after that approval, so an agent alone cannot add a channel that approves its own requests.

## 2. Ask

```text
ask_approval({
  action: "refund",
  summary: "Refund order 1042 (30 EUR)?",
  risk: "medium",
  amount: 30,
  wait_seconds: 45
})
```

You get a Telegram message with the summary and the buttons. If you answer within `wait_seconds`, the call returns the decision: `approved`, `denied`, `modified` or `needs_context`, with your comment. Otherwise it returns `pending` and the agent can carry on with other work.

`risk: "high"` requires `details` (up to 4,000 characters), shown to you before you decide. `options` adds up to 5 choices (40 characters each) besides approve and deny; picking one returns `modified` with the choice in `decision`. `approvers: ["chn_…"]` picks the channels; without it Brynth asks every active channel.

`ask_human({question: "Which plan should the new customer get?"})` asks an open question the same way; its answer has status `answered`.

## 3. Resume after a later answer

When you decide after the wait, Brynth puts a `request.resolved` event in the inbox (source `brynth`, `trust: "brynth"`). Save the task state before asking and pass its id as `state_ref`:

```text
state_save({task_id: "refund-1042", state: {order: 1042, step: "refund"}, note: "Waiting for approval"})
ask_approval({action: "refund", summary: "Refund order 1042 (30 EUR)?", state_ref: "refund-1042"})
```

Any later session, in any agent, finds the decision with `inbox_list({type: "request.resolved"})`, reloads the work with `state_load({task_id: "refund-1042"})` and goes on. `request_status({request_id: "req_…"})` reads a request at any time.

A request expires after `expires_in` (default `24h`, from `1m` to `7d`) and its status becomes `expired`.

## 4. Let the policy decide

Rules decide which actions need you. This one sends every email outside your domain to Telegram:

```text
policy_set({
  policy: {rules: [
    {match: {tool: "email_send", to_domain_not_in: ["acme.example"]}, effect: "require_approval", approvers: ["chn_…"]}
  ]},
  note: "Ask me before writing to customers"
})
```

A policy change is itself approved by a person before it applies. See [Requests and policy](/concepts/requests-and-policy.md).
