> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Canned responses and macros — the reply library model

> What a canned response is vs a macro, how personal and team scoping decides who can see and run each, how placeholders resolve at send time, and where the reply library sits next to the template lifecycle.

# Canned responses and macros — the reply library model

The reply library is the set of pre-authored content agents send from the inbox. It has two levels, and distinguishing them is the first modeling decision:

* **A canned response** is a named template blob — one reusable message body stored under a shortcut. It is content only: a shortcut like `/hours`, a title, a body, and an optional channel scope. When an agent types the shortcut in the composer, the stored body replaces it.
* **A macro** is a canned response plus more: an ordered chain of steps — send a message, add or remove contact tags, assign the conversation, set its status or priority, snooze it, schedule a follow-up, create a task, or escalate to an AI agent. The message step of a macro carries variable placeholders (`{{contact.first_name}}`, `{{agent.signature}}`) that resolve against the live conversation when the macro runs.

Rule of thumb: if you need a reusable message, that is a canned response. If "send the reply" always comes with two more bookkeeping steps, that is a macro. Macros exist so the bookkeeping runs as one confirmed action, with the editor rejecting conflicting steps (two priorities, two dispositions, a snooze after a close) at save time rather than at send time.

## Scoping — who can see and run each

The two levels carry different scoping rules.

**Canned responses** are one org-wide library. Owners and admins manage the entries through the settings endpoints; every agent in the workspace can use any entry from the composer. There is no personal canned response — the personalization lever on this level is the channel scope, not visibility. An entry with a `channel` value is offered only on conversations of that channel; an entry with no channel (or the literal `all`) is offered everywhere. That filtering happens server-side — the inbox composer requests only the active channel's subset instead of shipping the whole library to client-filter — and the list endpoint clamps any `limit` you pass to a 500-row maximum.

**Macros** carry a real access model, the same shape as saved views and routing rules elsewhere in the workspace:

* **Personal macros** belong to the agent who created them. Only the creator (or an owner/admin) can edit, delete, or run them, and nobody else sees them in the palette or the list.
* **Team (shared) macros** are created by owners and admins and are readable by everyone in the workspace. Optionally the creator narrows a shared macro to one or more team ids; then only active members of the listed teams see it in their palette. Owners and admins bypass the narrowing and always see the full library.

Folders follow the same split: a personal folder is the creator's private organization layer, a team folder is a shared grouping every agent sees.

The scope decision is part of authoring, not an afterthought. An agent iterating on a reply chain for themselves keeps it personal; a team lead narrows a shared macro to their team so refund templates do not clutter the sales palette; the owner publishes it workspace-wide once the wording is final.

## How resolution works at send time

A macro's message body is stored with its placeholders unresolved. Resolution happens at run time in a fixed order:

1. **Lookup.** Running a macro loads the stored definition, which is the placeholder map against the current conversation.
2. **Variable interpolation.** `{{contact.*}}` fields resolve from the contact profile, `{{agent.*}}` from the running agent's saved signature and name, `{{conversation.*}}` from the conversation the macro runs against. Anything that does not resolve renders as an empty string — a typo shows up as a missing word, not as a literal `{{...}}` in a customer-facing message.
3. **Locale selection.** A message step can carry one body per language. The run picks the body matching the conversation's detected language, falls back to the contact's stored language, then to English (the required fallback body). One "refund policy" macro serves a multilingual queue.
4. **Preview before commit.** Multi-step macros render every step against the live conversation — variables interpolated, relative times converted to exact timestamps — with zero side effects until the operator confirms. Once fired, re-running the same macro against the same conversation inside 30 seconds is debounced, so a double click cannot double-send.

This resolution layer is deliberately independent of the [template lifecycle](https://docs.orbit.devotel.io/concepts/template-lifecycle.md). Carrier-reviewed templates (WhatsApp, RCS, KakaoTalk, Zalo) are a separate object class: on those channels a macro's message step still has to reference an approved template, because the carrier's approval gate cannot be bypassed by an agent-created macro. On platform-only channels (SMS, MMS, email, and the rest) there is no review round-trip, so a macro's inline body sends directly. The reply library never interacts with the draft → pending → approved walk — it either references an already-approved template by id or ships its body on an approval-free channel. [Template delinquency](https://docs.orbit.devotel.io/concepts/template-lifecycle.md) pauses only the template-backed steps; channel-agnostic inline bodies are unaffected.

## Where the library appears

The same two libraries surface in three places:

* **Inbox** — the operator picker. The macro palette attached to the composer lists the macros visible to the current agent, grouped by folder, ranked by their own recent run count. Canned responses are reachable through the slash shortcut typed into the composer text. Both are the day-to-day surface.
* **Campaigns** — the template step. A campaign that needs a reusable body references a carrier-reviewed template by id; a canned response is not a campaign object. The distinction matters: campaigns go through the template lifecycle because they send at scale, while inbox replies go through the reply library because agents send them one conversation at a time.
* **Flows** — automation steps that send messages resolve the same way a macro's message step does: either reference an approved template or carry an inline body on a platform-only channel.

## A worked example

Create an org-wide canned response scoped to SMS:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/settings/canned-responses" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "shortcut": "/refund-sms",
    "title": "Refund policy (SMS)",
    "content": "Our refund policy: full refunds within 30 days, no questions asked.",
    "channel": "sms"
  }'
```

The `201` returns the generated `id` (`cr_...`) and `created_at`; a bad shape gets a `422`. From then on, every agent can type `/refund-sms` into the composer of an SMS conversation and have the body replace the shortcut.

The Inbox-use walkthrough for a macro: an agent opens a conversation, presses `/`, picks **Refund policy** from the filtered list, and sees the preview — the resolved message body, the tag, the snooze target rendered as an exact time, the disposition label. They confirm, and the chain runs atomically; if the send fails, the reversible steps that already ran (tag, snooze, disposition) roll back, so a half-applied macro never leaves the conversation tagged and snoozed around a message that never went out.

A team-scope example: the support team lead publishes the refund macro as **shared, narrowed to the support team**. Support members see it in the palette; sales members do not; the owner can still edit the wording after legal review because admins bypass the narrowing. An agent who wants the same chain only for themselves creates it as a personal macro instead — visible and runnable by that agent alone.

## See also

* [Macros and canned responses guide](https://docs.orbit.devotel.io/guides/macros-canned-responses.md) — the operator walkthrough for building, organizing, and applying both libraries
* [Template lifecycle and approval semantics](https://docs.orbit.devotel.io/concepts/template-lifecycle.md) — the carrier-review model macro message steps reference on approval-required channels
* [Settings API reference](https://docs.orbit.devotel.io/api-reference/endpoints/settings.md) — the canned-response CRUD contract


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.