From eae63c12ecd2bd655eb6ee40fe11e848867e6b47 Mon Sep 17 00:00:00 2001 From: Prabhat Singh <109069787+prabhat-singh-kore@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:21:41 +0530 Subject: [PATCH 1/4] Artemis Context Guide - Phase 3 implemented Artemis Context Guide - Phase 3 implemented --- .../abl/reference/agent-declaration.mdx | 27 ++++++++++++++ .../abl/reference/configuration-reference.mdx | 2 +- .../administration/workspace-and-team.mdx | 2 ++ agent-platform/channels/voice.mdx | 35 ++++++++++++++++++- agent-platform/context-and-prompts.mdx | 2 ++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/agent-platform/abl/reference/agent-declaration.mdx b/agent-platform/abl/reference/agent-declaration.mdx index 0b5745a6f..536f7b9f4 100644 --- a/agent-platform/abl/reference/agent-declaration.mdx +++ b/agent-platform/abl/reference/agent-declaration.mdx @@ -498,6 +498,33 @@ EXECUTION: Every key also accepts its camelCase spelling (`greetingStyle`, `confirmCriticalValues`, `spellSensitiveValues`). This delivery policy is separate from the per-output [scoped `barge_in`](/agent-platform/abl/reference/flow#scoped-barge-in) policy. +### Voice instructions and grounding guards + +`EXECUTION.voice.instructions` sets the agent's spoken-style rules and fills `## Voice Delivery Instructions` in the prompt. + +```yaml +EXECUTION: + voice: + instructions: "Speak warmly in plain sentences. No lists. One or two short sentences per answer." + grounding_guards: + tool_arguments: true + reply_figures: true + reply_repairs: true +``` + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `instructions` | `string` | The platform's own voice rules (plain speech, no markdown, no emoji, no numbered lists) | **Replaces** the platform's default voice formatting rules, not just adds to them. | +| `grounding_guards.tool_arguments` | `boolean` | `false` | Refuses a tool call whose arguments (an ID, say) can't be traced back to a tool result or session value already in the turn. | +| `grounding_guards.reply_figures` | `boolean` | `false` | Drops a spoken number or figure from the reply when no tool result or session value supports it. This only catches text that hasn't started playing yet. | +| `grounding_guards.reply_repairs` | `boolean` | `false` | Allows one repair pass when the model promises an action (sends a confirmation, say) but the matching tool call never actually ran. | + +Because `instructions` **replaces** the platform voice rules rather than extending them, its own "plain speech, no lists" wording is what keeps the agent from reading out bullet points or markdown on a voice channel -- restate that in your own text. An agent with a custom `SYSTEM_PROMPT:` doesn't get the default voice formatting rules either, for the same reason: state spoken-style rules in the prompt text itself, or in `EXECUTION.voice.instructions`. + +All three `grounding_guards` default to off and apply to voice channels only. `reply_figures` and `reply_repairs` work against values already present in the turn's tool results and session state, so a tool whose `MODEL_CONTEXT` strips a figure the model later needs to confirm will have that figure dropped from the spoken reply too. + +See [Voice agents](/agent-platform/channels/voice) for how these settings differ between pipeline and realtime voice, and [Voice coordinator policy](#voice-coordinator-policy) above for the realtime-only delivery-tone settings. + ### Complete execution example ```yaml expandable=true diff --git a/agent-platform/abl/reference/configuration-reference.mdx b/agent-platform/abl/reference/configuration-reference.mdx index 725a84899..6d2527043 100644 --- a/agent-platform/abl/reference/configuration-reference.mdx +++ b/agent-platform/abl/reference/configuration-reference.mdx @@ -22,7 +22,7 @@ ABL settings take effect in new conversations once saved, or once published and | [`EXECUTION.inline_gather`](/agent-platform/abl-reference/agent-declaration#configuration-properties) | Agent ABL | `false` (on in the voice profile) | `## Information Collection` instead of the `GATHER` list | | [`EXECUTION.compaction.*`](/agent-platform/context-compaction#size-limits-and-compaction) | Agent ABL | See [Context size, compaction, and budgets](/agent-platform/context-compaction) | Tool results, earlier turns, and `## Current Context` budgets | | `EXECUTION.models.summarization` | Agent ABL | Project tier | The model used for tool-result summaries | -| `EXECUTION.voice.instructions` | Agent ABL | -- | `## Voice Delivery Instructions` and voice formatting rules | +| [`EXECUTION.voice.instructions`](/agent-platform/abl-reference/agent-declaration#voice-instructions-and-grounding-guards) | Agent ABL | -- | `## Voice Delivery Instructions` and voice formatting rules | | `EXECUTION.guardrail_builtins` | Agent ABL | `false` | Whether a guardrail check can read `content`, `session_state`, and `tool_results` | | [Tool `MODEL_CONTEXT`](/agent-platform/abl-reference/tools#model_context-on-a-tool-result) (`FIELDS` / `TEMPLATE`) | Tool ABL | -- | What the model sees of a tool result, now and later | | [Response `MODEL_CONTEXT`](/agent-platform/abl-reference/flow#model_context-on-a-response) | Hook `RESPOND`, `COMPLETE`, `FLOW` step | -- | What the history records for a rich response | diff --git a/agent-platform/administration/workspace-and-team.mdx b/agent-platform/administration/workspace-and-team.mdx index b3704dff6..e5d56dde1 100644 --- a/agent-platform/administration/workspace-and-team.mdx +++ b/agent-platform/administration/workspace-and-team.mdx @@ -729,6 +729,8 @@ MEMORY: TTL: "{{env.MEMORY_TTL_DAYS}}d" ``` +The **Secret** flag only masks a variable's value in the Studio UI -- it doesn't change what the agent sends anywhere the variable is referenced. Referencing a secret variable in the agent's persona, goal, or limitations sends its resolved value to the model as plain prompt text, the same as referencing it in `RESPOND` sends it to the customer. Reserve secret variables for constructs the model and the customer never see -- HTTP tool endpoints, headers, and auth -- and keep anything referenced in the system prompt or a response non-secret. + ### Edit a variable Select the **Edit** icon next to a variable to change its value, description, or secret setting. Your change reaches new agent sessions immediately. diff --git a/agent-platform/channels/voice.mdx b/agent-platform/channels/voice.mdx index 239ed7e74..097c67454 100644 --- a/agent-platform/channels/voice.mdx +++ b/agent-platform/channels/voice.mdx @@ -561,4 +561,37 @@ Open a channel from **Deployments** > **Channels** > **Voice** > **Pipeline Voic Click **Save Changes** after switching the environment or the version. - \ No newline at end of file + +## Pipeline vs. realtime voice + +Pipeline voice (speech-to-text, agent, text-to-speech) and Realtime LLM Voice (speech-to-speech) build the agent's turn differently underneath the same ABL. Knowing which one a channel uses matters when authoring instructions, reasoning about history after a handoff, or sizing tool results. + +| | Pipeline voice | Realtime speech-to-speech | +|---|---|---| +| **System prompt** | The same chat prompt, plus `## Response Format (Voice Channel)`, `## Voice Delivery Instructions`, and the voice language policy | The same agent prompt and tools, plus a realtime operating section | +| **History** | The same history and compaction rules as chat | The provider holds the call's history itself. No history is sent on first connect. | +| **After a handoff** | The receiving agent sees history the same way chat does | Depends on the provider -- see below | +| **Tool results** | The same shaping and compaction as chat | Capped at 102,400 bytes, 8 levels deep, 64 keys per object, 128 array items, and 32,768 characters per string | + +Handoff replay on realtime channels varies by provider. OpenAI Realtime and Azure OpenAI Realtime resend the new agent's prompt with a replay of up to 8 recent messages (4,000 characters total, 700 per message). Amazon Nova Sonic opens a new stream with recent turns in a short block (also up to 4,000 characters, 700 per message). Grok Realtime replays every earlier caller utterance. Gemini Live starts a fresh session and replays history. + +### Authoring voice behavior in ABL + +The Studio settings on this page configure a channel. The agent's own spoken behavior is authored in ABL: + +- **Spoken-style rules and grounding guards** -- `EXECUTION.voice.instructions` and `EXECUTION.voice.grounding_guards`, which replace the platform's default voice formatting rules and can refuse ungrounded tool arguments or figures. See [Voice instructions and grounding guards](/agent-platform/abl-reference/agent-declaration#voice-instructions-and-grounding-guards). +- **Realtime delivery tone** -- `EXECUTION.voice.coordinator_policy` (tone, pace, brevity, interruption handling, accessibility read-backs). See [Voice coordinator policy](/agent-platform/abl-reference/agent-declaration#voice-coordinator-policy). +- **Per-response voice overrides** -- the `VOICE:` block on a `RESPOND` (SSML, plain text, provider, voice, speed) plus the step- and response-scoped `BARGE_IN`, `STREAMING`, and `END_OF_SPEECH_TURN_TYPE` overrides. See [Voice configuration](/agent-platform/abl-reference/rich-content#voice-configuration) and [Scoped barge-in](/agent-platform/abl-reference/flow#scoped-barge-in). +- **Listening and turn-taking** -- `CONVERSATION: listening:` (barge-in, no-input retries, caller backchannel, on-hold phrases, barge-in continuation merging). See [Voice turn-taking](/agent-platform/abl-reference/behavior-profiles#voice-turn-taking). +- **Low-latency defaults** -- new projects and voice channels get the `customer_service_voice_low_latency_v1` profile automatically: tighter compaction, the fast model tier for every operation, reasoning off, and inline gather on. The Studio side of this profile -- model routing, compaction budgets, and filler tuning -- is covered in [Voice low-latency profile](/agent-platform/administration/general-settings#voice-low-latency-profile). + +The low-latency profile does not fall back to the project's default model. If the workspace has no model assigned to the fast tier, voice turns have no model to call. + +```yaml +EXECUTION: + voice: + instructions: "Speak warmly in plain sentences. No lists. One or two short sentences per answer." + grounding_guards: + tool_arguments: true + reply_figures: true +``` diff --git a/agent-platform/context-and-prompts.mdx b/agent-platform/context-and-prompts.mdx index cb8cb07b9..3ff0579de 100644 --- a/agent-platform/context-and-prompts.mdx +++ b/agent-platform/context-and-prompts.mdx @@ -60,6 +60,8 @@ If a referenced value is unset, the literal `{{customer_tier}}` text stays in th There is no per-entry setting to hide one declared memory value from the model while leaving the rest of a `MEMORY: SESSION:` block visible. Use the options in [Keeping a value out of the prompt](#keeping-a-value-out-of-the-prompt) above instead. +`{{config.*}}` and `{{env.*}}` values are left out of `## Current Context` automatically, but that protection doesn't extend to a `{{env.KEY}}` reference written directly into `GOAL`, `PERSONA`, `LIMITATIONS`, `SYSTEM_PROMPT:`, or `RESPOND` -- the resolved value is sent as plain prompt text, same as any other reference. [Referencing environment variables](/agent-platform/administration/workspace-and-team#reference-environment-variables) in those fields is supported and often useful, but only for a variable that isn't marked **Secret**. A secret variable referenced in a model-visible or customer-visible field defeats the point of marking it secret -- the Secret flag only masks its value in the Studio UI. + --- {{related}} From f24efcbd1c6514beda4b2b1f769591faf655b4e4 Mon Sep 17 00:00:00 2001 From: siddharthmenon-7 Date: Thu, 22 Oct 2026 19:41:56 +0530 Subject: [PATCH 2/4] Updated channels docs --- agent-platform/channels/ai-for-work.mdx | 269 +++++++++---- agent-platform/channels/email.mdx | 212 ++++++++++ .../channels/genesys-open-messaging.mdx | 332 ++++++++------- agent-platform/channels/genesys.mdx | 342 ++++++++-------- agent-platform/channels/instagram.mdx | 354 +++++++--------- agent-platform/channels/kore-agent-assist.mdx | 298 ++++++-------- agent-platform/channels/line.mdx | 381 ++++++++---------- agent-platform/channels/messenger.mdx | 358 +++++++--------- agent-platform/channels/ms-teams-copilot.mdx | 335 +++++++++------ agent-platform/channels/slack.mdx | 348 ++++++++++------ agent-platform/channels/telegram.mdx | 330 ++++++++------- agent-platform/channels/twilio.mdx | 330 +++++++-------- agent-platform/channels/whatsapp.mdx | 17 +- agent-platform/channels/zendesk.mdx | 363 +++++++---------- 14 files changed, 2250 insertions(+), 2019 deletions(-) create mode 100644 agent-platform/channels/email.mdx diff --git a/agent-platform/channels/ai-for-work.mdx b/agent-platform/channels/ai-for-work.mdx index 2f33f19df..e834c5242 100644 --- a/agent-platform/channels/ai-for-work.mdx +++ b/agent-platform/channels/ai-for-work.mdx @@ -3,152 +3,251 @@ title: Set up AI for Work sidebarTitle: AI for Work --- -[Back to channels](/agent-platform/channels) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect your agent to Kore.ai AI for Work, the Employee Experience (EX) platform, as a bidirectional messaging integration. Employees reach the agent through a published Autonomous Agent in AI for Work, and AI for Work reaches the agent through an endpoint URL and connection secret that you generate in Artemis. +Connect your agent to Kore.ai AI for Work, the Employee Experience (EX) platform, as a bidirectional messaging integration. Employees reach the agent through a published Autonomous Agent in AI for Work. AI for Work calls Artemis through a generated endpoint and signs every request with a connection secret and a user identity token. -Artemis labels this channel **AIforWork**. The product it connects to is documented as AI for Work. This article uses **AIforWork** for the on-screen label and AI for Work for the product. +The setup requires: -## Before you begin +1. [Create the connection in Artemis](#create-the-connection-in-artemis) and copy its two generated values. +2. [Link the connection in AI for Work](#link-the-connection-in-ai-for-work) and publish the agent. +3. [Validate the integration](#validate-the-integration) with signed requests. -You need administrator access to the AI for Work Admin Console and permission to create and publish Autonomous Agents in the target workspace. You also need a project in Artemis with at least one deployed version in the environment you plan to bind the connection to. +After setup, Artemis verifies each AI for Work request, scopes the session to the connection, the verified email, and the conversation context, and answers with the agent deployed in the bound environment. -Create the connection in Artemis first. The endpoint URL and connection secret it generates are the inputs to the AI for Work side of the setup. +**Important considerations** -## Create the channel connection in Artemis +- **The Connection ID selects the connection**: AI for Work sends each message to `/api/v1/channels/ai4w/{connectionId}/message`. Artemis generates the ID, so you never choose a routing value. +- **The Connection Secret is reveal-once**: Artemis shows it only at creation. If you lose it or suspect exposure, replace the connection or rotate the secret before you send more traffic. +- **Every request needs two authentication layers**: An HMAC signature made with the Connection Secret, and a trusted AI for Work identity JWT. Artemis validates each one independently. +- **Pause and Resume control traffic**: Select **Pause** in the connection header to stop all AI for Work traffic. - - - Open Artemis, select the required project, and go to **Deployments** -> **Channels** -> **AIforWork** -> **+ New**. On the **New AIforWork Connection** dialog, provide the following fields. +Artemis labels this channel **AIforWork**. This article uses **AIforWork** for on-screen labels and AI for Work for the product. - | Field | Description | - | ----- | ----------- | - | **Display Name** | A label for the connection, for example `AIforWork Production`. Up to 255 characters. | - | **Environment** | Select an environment to follow its active deployment. If no environment has an active deployment yet, leave the default and bind the connection later from the **Deployment** tab. | - | **Provider Verification Strength** | **Weak (default)** or **Strong**. Choose **Strong** only for channels or providers whose identity assertions you trust for stronger continuity and linking decisions. | - | **Initial Status** | **Active** connections can be used immediately. **Inactive** connections stay saved but disabled until you activate them. Set this to **Active**. | +## Prerequisites - Select **Create**. - +Confirm these before you start. - - The **AIforWork Connection Created** dialog shows the **Endpoint URL** and the **Connection Secret**. Copy both values and store the secret securely, then select **Done**. +- Administrator access to the AI for Work Admin Console, with permission to create and publish Autonomous Agents in the target workspace. +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. +- A server-side secret store in AI for Work for the Connection Secret. - The connection secret appears only once and can't be retrieved afterward. If you lose it, open the connection and select **Rotate** on the **Overview** tab to issue a new one. Rotating the secret invalidates the previous value, so update the AI for Work configuration with the new secret. +--- - AI for Work uses the endpoint URL and secret to sign its requests with HMAC. - - +## Create the connection in Artemis + +Create the connection first. Artemis generates the endpoint and secret that AI for Work needs. + +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **AIforWork** -> **+ New**. The **New AIforWork Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see. Name it for the AI for Work tenant and environment. Routing ignores it. | + | **Environment** | The environment whose active deployment answers AI for Work traffic. Leave the working copy default only while you build and test. | + | **Provider Verification Strength** | How far the runtime trusts the provider's identity assertion when it links a user to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | **Active** accepts authenticated traffic immediately. **Inactive** saves the connection without letting AI for Work start sessions. | + +4. Select **Create**. +5. Copy both generated values before you close the reveal dialog. + +| Value | Format | Where it goes | +|---|---|---| +| **Endpoint URL** | `https://{host}/api/v1/channels/ai4w/ai4w_c_{id}/message` | The **Endpoint URL** field in AI for Work. Paste it whole, including the `/message` suffix. | +| **Connection Secret** | Begins with `abl_cs_` | AI for Work's server-side secret store. Never send it to a browser, put it in a URL, log it, or use it as the JWT signing key. | + +--- ## Link the connection in AI for Work +Register the Artemis connection as the backend of an Autonomous Agent. Use the AI for Work environment that matches the Artemis connection, and keep development, staging, and production on separate connections and secrets. + 1. Open the AI for Work Admin Console, switch to the target workspace, and go to **AI Agents** -> **Autonomous Agents**. 2. Select **Create agent**, then create the agent from scratch. - 3. Enter the agent name and the purpose of the app. AI for Work uses the purpose for query routing and training. + 3. Enter the agent name and its purpose. AI for Work uses the purpose for query routing. 1. In **Configure agentic app**, select **Add using credentials**. - 2. On the **Link using credentials** dialog, enter the **Endpoint URL** and the **Connection Secret** you copied from Artemis. + 2. On the **Link using credentials** dialog, paste the **Endpoint URL** and the **Connection Secret**. 3. Select **Run and Save**. - Select **Browse and Link Projects** on the same dialog to pick the app directly from an Agent Platform workspace instead of entering credentials. Use the credentials method when the agent is in a workspace you can't browse from AI for Work, or when you want the connection pinned to a specific Artemis channel connection. + Don't trim the `/message` suffix, swap in another Connection ID, or use a generic AI for Work webhook path. - Select **Async** as the mode and test the connection. A successful test reports that the async connection succeeded. + 1. Select a mode and test the connection. + 2. If you select **Async**, set the **Callback Base URL** on the Artemis connection's **Configuration** tab, so Artemis can deliver responses and proactive notifications back to AI for Work. - Async mode suits agents that take longer than the 60-second sync timeout. When you use async mode, set the **Callback Base URL** on the Artemis connection's **Configuration** tab so the agent can return responses and proactive notifications to AI for Work. + Async suits agents that run longer than the 60-second sync timeout. - Select **Continue**, then select **Publish**. Choose whether to publish to everyone in the account or to limited users. For the full set of publishing options, see the [AI for Work custom agents documentation](https://docs.kore.ai/ai-for-work/custom-agents#publishing-your-agent). + Select **Continue**, then **Publish**, and choose everyone in the account or limited users. See [publishing your agent](https://docs.kore.ai/ai-for-work/custom-agents#publishing-your-agent). -## Key values reference +--- + +## Authentication + +AI for Work must send both authentication layers on every request. Artemis rejects a request that fails either one. + +| Header | Value | +|---|---| +| `Authorization` | `Bearer `, a trusted AI for Work identity token | +| `X-Signature-Nonce` | A unique value per attempt | +| `X-Timestamp` | The current timestamp | +| `X-Signature` | `sha256=`. The `sha256=` prefix is optional. | + + + + Compute the signature over the exact UTF-8 bytes you send. A gateway or client that parses and re-serializes JSON changes the bytes and breaks the signature. + + + + Compute HMAC-SHA256 with the `abl_cs_` secret over `inbound:{nonce}.{timestamp}.{rawBody}`, and encode the digest as lowercase hex. Send the same nonce and timestamp in their headers. + + + + Use a platform-approved issuer and audience, and include the `sub`, `email`, `accountId`, and `authLevel` claims. + -| Value | Where it comes from | Where it's used | -| ----- | ------------------- | --------------- | -| **Endpoint URL** | The **AIforWork Connection Created** dialog in Artemis, or the connection's **Overview** tab | The **Endpoint URL** field on the AI for Work **Link using credentials** dialog | -| **Connection Secret** | The **AIforWork Connection Created** dialog in Artemis; shown only at creation time | The **Connection Secret** field on the AI for Work **Link using credentials** dialog | -| **Callback Base URL** | Your AI for Work instance | The **Callback Base URL** field on the Artemis connection's **Configuration** tab | + + On the first valid request, Artemis can bind the connection to the JWT `accountId`. It then rejects requests from another account unless an administrator changes that policy. + + + +--- -## Pass custom metadata +## Message request -AI for Work can pass custom metadata to the connected Artemis app. In **Configure agentic app**, open **\ Meta Data** and add the metadata you want to send. +Send each message as an HTTPS POST with a JSON body. -Inside Artemis, the expression that reads the metadata differs by surface. The following examples read an `email` key. +| Field | Required | Rule | +|---|---|---| +| `text` | Yes | Up to 10,000 characters. | +| `agentContextId` | Yes | Identifies the AI for Work conversation. Reuse it for follow-up turns, and don't replace it with a per-message UUID. | +| `conversationHistory` | No | Up to 100 prior items. Send only context AI for Work owns, and don't repeat the current text. | +| `files` | No | Up to 10 file references. See [Files](#files). | +| `metadata`, `sessionMetadata` | No | Structured objects. Keep secrets and authorization decisions out of them. | + +Artemis keeps conversation continuity from three values together: the connection, the verified email, and `agentContextId`. + +### Response modes + +Select a default mode in AI for Work. Send the `X-Response-Mode` header to override it for one request. Artemis reports the mode it used in `X-Response-Mode-Used`. + +| Mode | Behavior | +|---|---| +| `auto` | Streams when the `Accept` header includes `text/event-stream`. Otherwise returns a completed JSON result, or `202` with a working envelope while Artemis continues. | +| `sync` | Waits for the turn and returns the response, `sessionId`, outcome status, response metadata, and any error details. Keep client and gateway timeouts above the runtime's sync budget. | +| `stream` | Send `X-Response-Mode: stream` and accept `text/event-stream`. Handle `chunk`, `done`, and `error` events, and tolerate heartbeat comments. | +| `async` | Returns `202` with `requestId` and `sessionId`, then delivers the result to the **Callback Base URL**. Artemis treats a repeated external message ID as the same request. | + +For async delivery, the callback must be an approved HTTPS destination, and it must verify Artemis's outbound HMAC signature before it accepts the payload. + +### Files + +AI for Work sends file references, and Artemis downloads them server-side. + +- Send each file as a name, a MIME type, and a short-lived signed HTTPS URL. Never embed file bytes or reusable storage credentials. +- File names allow up to 255 characters, and signed URLs up to 2,048 characters. +- Every download passes SSRF checks and the tenant and project attachment policy for host, MIME type, size, and per-session limits. + +### Custom metadata + +AI for Work can pass custom metadata to the agent. In **Configure agentic app**, open **Meta Data** and add the keys you want to send. Read them in Artemis with the expression for each surface, shown here for an `email` key. | Surface | Expression | -| ------- | ---------- | +|---|---| | Agent | `{{_metadata.email}}` | | Workflow tool | `{{vars._session._metadata.email}}` | | HTTP tool | `{{session._metadata.email}}` | -## Manage the channel connection +--- -Opening a connection from **Deployments** -> **Channels** -> **AIforWork** shows three tabs: **Overview**, **Configuration**, and **Deployment**. The header shows the connection name, the bound environment, the status, and the channel type, along with **Pause** and delete actions. +## Validate the integration - - - The **Connection Summary** shows these fields. - - | Field | Description | - |-----------------|-----------------------------------| - | **Status** | For example: *Active* | - | **Created** | Timestamp the connection was created | - | **Updated** | Timestamp of the last change | - | **Environment** | For example: `dev` | - | **Source Type** | `Channel Connection` | - | **Source ID** | Unique connection identifier (UUID) | - - Under **Setup Instructions**, the tab shows the **Endpoint URL** to enter in AI for Work and the masked **Connection Secret**. Select **Rotate** to issue a new secret. The full secret is shown only at creation time and can't be retrieved. - +Run these checks from AI for Work, or from any client that signs requests the same way. - - Under **General**, configure the following. +1. If your integration supports a preflight, call the connection's `/info` endpoint with the same HMAC and JWT chain. Confirm it returns connection metadata without the secret. +2. Send one signed text message with a fresh nonce, a current timestamp, and a trusted JWT. Confirm the expected `X-Response-Mode-Used` and an agent response. +3. Send a second message with the same verified email and `agentContextId`. Confirm the agent resumes the same session and uses the earlier context. +4. Confirm each of these fails without starting an agent turn: a changed raw body, a stale timestamp, a replayed nonce, an invalid JWT issuer or account, an unapproved callback, and a rejected file. - | Field | Description | - | ----- | ----------- | - | **Display Name** | The label for the connection. | - | **Provider Verification Strength** | **Weak (default)** or **Strong**. Choose **Strong** only for channels or providers whose identity assertions you trust for stronger continuity and linking decisions. | +--- - Under **AIforWork Settings**, configure the following. +## Manage the channel connection - | Field | Description | - | ----- | ----------- | - | **Callback Base URL** | The base URL where ABL sends async responses and proactive notifications. Required when AI for Work uses the async response mode. | +Open a connection from **Deployments** -> **Channels** -> **AIforWork** to manage it. The page has a header, two tabs, and a summary panel on the right. - #### Authorization message +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. **Pause** and **Resume** control traffic, and the **...** overflow menu holds the other connection-level actions. - The **Authorization Message** panel controls the message shown when a tool needs the user to authorize. Edit the **Message template** directly, or use the **Insert** buttons to add the most common variables at the cursor. +**Summary panel.** Stays visible on every tab. - The default template asks the user to authorize the pending verifications and then lists each one as a numbered profile name with its authorization link. +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **AIforWork** and **Channel Connection**. | +| **Identifier** | The generated `ai4w_c_` Connection ID this connection routes on. | +| **Webhook URL** | The endpoint AI for Work calls, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | - Expand **Show variables** to see the full set of supported variables. + + + Update the connection's behavior. **AIforWork Settings** holds the provider-specific fields. + + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts the provider's identity assertion. | + | **Callback Base URL** | Where Artemis sends async responses and proactive notifications. Required when AI for Work uses async mode. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. | - | Scope | Variables | Notes | - | ----- | --------- | ----- | - | Message scope | `{{total}}`, `{{completed}}`, `{{remaining}}` | Counts for the session's pending authorizations. Use these anywhere in the template. | - | Item scope | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Valid only inside the repeat block. | - | Repeat block | `{{#authorizations}}`, `{{/authorizations}}` | Wraps the item scope variables and repeats the enclosed text once per pending authorization. | + Insert variables into the **Message template** from the chips below the editor, select **Show more** for the full list, and select **Show preview** to check the result. - Expand **Show preview** to see the template rendered with sample values. At runtime the platform fills these from the live session's pending authorizations. + | Scope | Variables | + |---|---| + | Whole message | `{{total}}`, `{{completed}}`, `{{remaining}}` | + | Repeat block | `{{#authorizations}}` ... `{{/authorizations}}`, which repeats once per pending authorization | + | Inside the block | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | - Select **Save Changes** to apply any changes. + Select **Save Changes** to apply your changes. - The **Deployment** tab shows these fields. + Choose which deployed version answers AI for Work. - | Field | Description | - |-----------------------|---------------------------------------------------------------------------------------------------------------------| - | **Agent Version** | An **Environment** dropdown (for example: `Development`) that selects which deployed version handles incoming messages. | - | **Active Deployment** | Shows the bound deployment version and when it was deployed. | + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Select **Save Changes** after switching the environment. + Select **Save Changes** after you switch the environment. - \ No newline at end of file + + +--- + +## Troubleshoot connection issues + +Most failures trace to the signature, the JWT, or a reused nonce. + +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Connection not found | Wrong or edited endpoint, or an inactive connection | Paste the full generated **Webhook URL** from the summary panel, and confirm the connection is **Active**. | +| Signature fails | The signed bytes or secret don't match | Sign `inbound:{nonce}.{timestamp}.{rawBody}` with the matching `abl_cs_` secret, keep the exact raw JSON bytes, and send the digest as hex. | +| JWT rejected | The token doesn't meet the trust rules | Verify the issuer, audience, signature algorithm, token time window, and the `email`, `accountId`, and `authLevel` claims. | +| A valid request becomes unauthorized | Replayed nonce or stale timestamp | Use a unique nonce and a current timestamp on every attempt. Don't retry by replaying the same signed request. | +| Async accepts the request but no callback arrives | Missing or unreachable callback | Save an approved **Callback Base URL**, check its network reachability, and validate the outbound signature before processing the body. | +| Text works but files don't | A file fails the download or policy checks | Check the signed URL lifetime, approved host, MIME type, size, file count, and project attachment policy. | +| AI for Work requests stop after you lose the secret | The secret is gone and AI for Work holds an old value | Replace the connection or rotate the secret, then update the **Connection Secret** in AI for Work. | + +{{related}} + +- [Channels](/agent-platform/channels) +- [Set up Kore Agent Assist](/agent-platform/channels/kore-agent-assist) +- [AI for Work custom agents](https://docs.kore.ai/ai-for-work/custom-agents) \ No newline at end of file diff --git a/agent-platform/channels/email.mdx b/agent-platform/channels/email.mdx new file mode 100644 index 000000000..e7923c466 --- /dev/null +++ b/agent-platform/channels/email.mdx @@ -0,0 +1,212 @@ +--- +title: Set up Email +sidebarTitle: Email +--- + +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) + +Connect your agent to email so it answers customer messages and keeps each mail thread as one conversation. Artemis generates an inbound address for the connection, receives mail through SMTP, and sends replies through SMTP or Microsoft Graph. + +The setup requires: + +1. [Create the connection in Artemis](#create-the-connection-in-artemis) and copy its generated inbound address. +2. [Route inbound email](#route-inbound-email) to that address. +3. [Configure outbound replies](#configure-outbound-replies) through SMTP or Microsoft Graph. +4. [Verify the connection](#verify-the-connection) with a complete email conversation. + +After setup, Artemis matches each message to the connection by its recipient address, finds the conversation from the thread headers, and replies to the sender in the same thread. + +**Important considerations** + +- **The generated recipient selects the connection**: Artemis resolves the connection during SMTP `RCPT TO` from its generated inbound address. There's no credential or routing field to fill in. +- **Email doesn't use a Request URL**: Don't look for an Events Request URL or configure an HTTP webhook. Inbound mail enters through SMTP. +- **The inbound domain belongs to your platform administrator**: Artemis builds the address under the administrator-owned `EMAIL_INBOUND_DOMAIN`. If that domain isn't publicly routable or approved for your environment, ask the administrator to complete SMTP and DNS setup. +- **Thread headers keep conversations together**: `Message-ID`, `In-Reply-To`, and `References` identify the thread. A mail client or rule that strips them breaks continuity. + +## Prerequisites + +Confirm these before you start. + +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. +- A platform administrator who manages SMTP ingress, the inbound domain, and the outbound SMTP relay. +- For Microsoft Graph replies, an Azure app registration with admin-consented permission to send mail as the sender mailbox. + +--- + +## Create the connection in Artemis + +Create the connection first. Artemis generates the inbound address when you create it. + +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Email** -> **+ New**. The **New Email Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see. Name it for the business mailbox and environment. It isn't the inbound address. | + | **Provider** | The outbound transport. Keep the default, and switch to Microsoft Graph from the **Settings** tab after creation. | + | **Environment** | The environment whose active deployment processes incoming email. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | How far the runtime trusts the provider's identity assertion when it links a sender to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | **Active** accepts mail immediately. SMTP rejects mail for an **Inactive** connection as an unknown recipient. | + +4. Select **Create**. Artemis generates a random local part under the platform's inbound domain. +5. Open the connection and copy the full inbound address from **Identifier** in the summary panel. Keep both the local part and the domain, and don't substitute your public support mailbox. + +--- + +## Route inbound email + +Get customer mail to the generated address. Each step depends on the one before it. + +1. Send customer mail straight to the generated address, or forward a dedicated mailbox such as your support address to it. Confirm forwarding keeps the original sender and the thread headers. +2. Ask your platform administrator to validate SMTP ingress. Production needs the inbound domain's mail routing to reach the runtime SMTP service. Port 2525 is the default internal and development listener. Public MX delivery normally reaches an approved edge on port 25, which forwards internally. +3. Preserve the RFC 5322 thread headers. Artemis records `Message-ID` for each inbound message and uses `In-Reply-To` and `References` to find the active conversation. When a client strips them, Artemis falls back to normalized `Re:` and `Fwd:` subject matching. +4. Address one generated channel recipient per SMTP transaction. Artemis rejects unknown addresses with `550`, and rejects a transaction whose recipients belong to different connections, so one message never crosses a project or connection boundary. + +--- + +## Configure outbound replies + +Choose the outbound transport on the saved connection's **Settings** tab. + + + + SMTP uses the administrator-owned `SMTP_RELAY` settings, so Artemis shows no per-connection SMTP credentials. + + 1. Keep **Provider** under **Outbound Transport** set to **SMTP (Default)**. + 2. Confirm the relay, sender policy, SPF, DKIM, DMARC, and deliverability with your platform administrator. + + + + Use Microsoft Graph to send replies from a dedicated Microsoft 365 mailbox. Artemis uses the client-credentials flow with the Graph `.default` scope to create and send a draft as that mailbox. + + 1. Set **Provider** under **Outbound Transport** to **Microsoft Graph API**. + 2. Enter the fields below from your Azure app registration. + 3. Select **Save Changes**. + + | Artemis field | Source | + |---|---| + | **Azure AD Tenant ID** | The app registration's **Directory (tenant) ID** | + | **Application (Client) ID** | The app registration's **Application (client) ID** | + | **Sender Mailbox Address** | The Microsoft 365 mailbox that sends replies | + | **Client Secret** | A client secret from the app registration. Artemis encrypts it. On later edits, leave the field blank to keep the stored value. | + + Grant the Microsoft Graph application permission to create and send mail, and complete admin consent. Where your Microsoft 365 policy supports it, restrict the app to the sender mailbox. + + + +To brand replies, add **Header HTML** and **Footer HTML** on the **Templates** tab, and optionally include the five-point CSAT rating block. Review the result in common mail clients before production. + +--- + +## Verify the connection + +Each check exercises a different part of the email path. + +1. From a real external address, send plain text with a unique subject to the business mailbox or generated address. Confirm the agent sends one `Re:` reply to your **From** address. +2. Reply to the agent without changing the thread. Confirm Artemis resumes the same session instead of starting a new conversation. +3. Add CC and BCC recipients. Confirm replies copy the CC recipients, except the channel's own address, and leave BCC recipients off. +4. Send an allowed attachment, and one over the limit. Confirm the allowed file reaches the agent and SMTP rejects messages over 25 MB. +5. Send a message marked `Auto-Submitted` with any value other than `no`, and confirm Artemis ignores it. + +### Email behavior and limits + +Artemis applies these rules to every message. + +| Area | Behavior | +|---|---| +| Inbound text | Artemis passes the newest visible reply to the agent and removes quoted history, signatures, and forwarded-message headers. | +| Threading | RFC 5322 identifiers come first. `Re:` and `Fwd:` subject matching is a fallback only. | +| Subject | Replies reuse the inbound subject and add `Re:` only when it's missing. | +| Recipients | Replies keep original CC recipients, except the channel address. Artemis never forwards BCC. | +| Attachments | 25 MB total per message. Individual files follow the project attachment policy, with a 20 MB fallback. A failed upload doesn't block the text. | +| Output | Non-streaming and text-oriented. Artemis renders agent markdown as sanitized email HTML, without action widgets or other channel-native controls. | +| Loop prevention | Artemis ignores automatic replies and drops its own replies, marked with `X-ABL-Source`, if they return. | + +--- + +## Security and environment boundaries + +The embedded SMTP receiver doesn't require SMTP AUTH, so protect the email path deliberately. + +- **Edge controls**: Manage the production edge, DNS, network policy, recipient validation, rate controls, and abuse protection with your platform administrator. +- **Graph secret**: Store the Client Secret only in the encrypted connection field, and rotate it immediately if someone exposes it. +- **Template HTML**: Treat Header and Footer HTML as trusted administrator configuration. Keep scripts, forms, remote resources, and sensitive data out of them. +- **Agent output**: Artemis renders markdown images as text links rather than image tags, so replies carry no remote tracking pixels. It neutralizes `javascript`, `vbscript`, and `data` link schemes. +- **Environments**: Use separate inbound addresses, routing rules, outbound senders, Azure apps, and connections for development, staging, and production. + +--- + +## Manage the channel connection + +Open a connection from **Deployments** -> **Channels** -> **Email** to manage it. The page has a header, three tabs, and a summary panel on the right. + +**Header.** Shows the connection name, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. + +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Email** and **Channel Connection**. | +| **Identifier** | The generated inbound address this connection receives mail on. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + + + + Update the connection and its outbound transport. + + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | Under **Email Settings**. How far the runtime trusts the provider's identity assertion. | + | **Provider** | Under **Outbound Transport**. **SMTP (Default)** or **Microsoft Graph API**, which adds the Graph fields. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + + Select **Save Changes** to apply your changes. + + + + Brand outbound replies under **Email Template**. + + | Setting | Description | + |---|---| + | **Header HTML** | HTML that Artemis adds above every reply. | + | **Footer HTML** | HTML that Artemis adds below every reply. | + | **Include CSAT feedback rating in outbound emails** | Adds a signed five-point rating block to replies. | + + Select **Save Changes** to apply your changes. + + + + Choose which deployed version answers email. + + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | + + A connection on **Working Copy (draft)** shows a warning, because the working copy changes as you edit the agent. Bind it to a published environment before production. Select **Save Changes** after you switch the environment. + + + +--- + +## Troubleshoot connection issues + +Most failures trace to mail routing, thread headers, or the outbound transport. + +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Mail bounces with `550` | Unknown or inactive recipient | Copy the exact address from **Identifier**, confirm the connection is **Active**, and send one channel recipient per transaction. | +| Mail never reaches Artemis | The inbound domain doesn't route to the runtime | Ask your platform administrator to confirm DNS, MX, and SMTP ingress for the inbound domain. | +| Replies don't send | Outbound transport misconfigured | For SMTP, confirm the relay with your administrator. For Graph, check every Graph field, then inspect the connection's delivery diagnostic. | +| Graph returns authorization or configuration errors | Azure app or mailbox setup | Confirm the Tenant ID, Client ID, Sender Mailbox Address, Client Secret, application permission, admin consent, and mailbox access policy. | +| A reply starts a new conversation | Thread headers lost | Inspect `In-Reply-To` and `References` after forwarding, and avoid providers or rules that rebuild messages and drop RFC 5322 headers. | +| Text arrives but the attachment doesn't | A file breaks a limit or policy | Compare it with the 25 MB total limit and the project attachment count, size, MIME, and extension policy, then inspect upload logs. | +| Artemis silently ignores expected mail | Loop prevention dropped it | Confirm the message doesn't carry an `Auto-Submitted` value other than `no`, or an `X-ABL-Source` header. | + +{{related}} + +- [Channels](/agent-platform/channels) +- [Set up Slack](/agent-platform/channels/slack) +- [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file diff --git a/agent-platform/channels/genesys-open-messaging.mdx b/agent-platform/channels/genesys-open-messaging.mdx index 1c37fb358..ba205fe88 100644 --- a/agent-platform/channels/genesys-open-messaging.mdx +++ b/agent-platform/channels/genesys-open-messaging.mdx @@ -1,216 +1,246 @@ --- -title: Genesys Open Messaging +title: Set up Genesys Open Messaging sidebarTitle: Genesys Open Messaging --- [Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Deploy your agent through Genesys Cloud Open Messaging. Connect your Genesys Open Messaging integration to the platform by configuring the required provider details, authentication, and signed webhook. +Connect your agent to Genesys Cloud Open Messaging through a project-scoped, signed webhook. You bind a Genesys Open Messaging integration and an Auth Profile to the connection, validate the path in diagnostics mode, then enable live conversations. - - **Webhook Connection Token and Webhook Signature Secret are different.** The connection token identifies the connection through the webhook URL, while the signature secret verifies the authenticity of incoming requests. - +The setup requires: -## Create or select an Open Messaging integration in Genesys Cloud +1. [Prepare Genesys Cloud](#prepare-genesys-cloud) and its authentication. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection and copy its reveal-once values. +3. [Webhook configuration in Genesys](#webhook-configuration-in-genesys): set the signed webhook, or provision it from Artemis. +4. [Validate and enable](#validate-and-enable) the connection. + +After setup, Genesys posts each customer message to Artemis. Artemis verifies the signature, queues the message, and sends the agent's reply back through the Genesys Platform API. + +**Important considerations** + +- **The connection token selects the connection**: Artemis hashes the final `/webhooks/{connectionToken}` path segment and matches it to the project connection. The generic webhook path can't select a connection. +- **Three values, three jobs**: The connection token routes inbound requests. The signature secret proves the request body came from the integration. The Integration ID identifies the integration for outbound calls. +- **The full endpoint is reveal-on-create**: Artemis stores the token only as a SHA-256 hash and redacts credentials after creation. If you lose the plaintext token, create a new connection. +- **Start in diagnostics mode**: **Diagnostics only** permits setup checks without running live conversations. Switch to **Enabled** only after every check passes. + +## Prerequisites + +Confirm these before you start. + +- Genesys Cloud admin access in the organization that owns the Open Messaging integration. +- A Genesys OAuth client that can send Open Messaging inbound messages, structured responses, and receipts. +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. + +--- + +## Prepare Genesys Cloud + +Do this before you open the Artemis dialog. Select **Open Genesys Cloud** in the setup guide to jump straight there. - - Sign in to the Genesys Cloud organization that owns the Open Messaging integration. Select the correct Genesys region because the platform uses it to connect to the corresponding Genesys Platform API host. + + Sign in to the regional Genesys Cloud organization that owns the Open Messaging integration. Artemis uses the region to select the matching Genesys Platform API host. - - In Genesys Cloud, create or select the required Open Messaging integration and copy its **Integration ID**. + + In Genesys Cloud Admin, create or select the Open Messaging integration and copy its **Integration ID**. - Do not use a Bot Connector Stream ID, Audio Connector integration ID, organization ID, or OAuth client ID. + Don't substitute a Bot Connector Stream ID, an Audio Connector integration, an organization ID, or an OAuth client ID. - Create an active Auth Profile for the Genesys connector using OAuth 2.0 Client Credentials or Bearer authentication. The platform uses this profile for outbound Genesys Platform API calls. + In Artemis, create a project integration Auth Profile for connector `genesys`, using OAuth 2.0 Client Credentials or Bearer authentication. Artemis uses it only for outbound Genesys Platform API calls. - - Ensure that the Genesys OAuth client has the permissions required to send Open Messaging inbound messages, structured responses, and receipts. - - Use separate clients, integrations, and Auth Profiles for development and production environments. + + The OAuth client must send Open Messaging inbound messages, structured responses, and receipts for this integration. Keep development and production clients, integrations, and profiles separate. -## Integrate the Genesys Open Messaging connection +--- - - - Open Artemis, select the required project, and go to **Deployments** -> **Channels** -> **MESSAGING** -> **Genesys Open Messaging** -> **+ New**. - +## Artemis channel configuration - - Enter the required provider and authentication details. +Create the connection with the Genesys values. Artemis generates the webhook token and signature secret in the dialog. - | Field | Description | - | --- | --- | - | **Display Name** | A label for the connection, for example `Genesys Open Messaging Production`. Up to 255 characters. | - | **Genesys Region** | The region that hosts your Genesys Cloud organization. | - | **Organization ID** | The identifier for your Genesys Cloud organization. | - | **Integration ID** | The Open Messaging Integration ID. | - | **Activation Mode** | Select **Diagnostics only** initially to validate the connection before processing live traffic. | - | **Delivery Mode** | Keep **External bridge** unless a different delivery mode is explicitly required. External bridge is the standard bot-facing channel — it's what makes the connection available to the Genesys Open Messaging agent-transfer handoff. | - | **Genesys Auth Profile** | An active Auth Profile configured for the Genesys integration. | - - The Integration ID is used as the external identifier for outbound provider calls. The selected Auth Profile must be active and configured for the Genesys integration. - +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Genesys Open Messaging** -> **+ New**. The **New Genesys Open Messaging Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Under **Open Messaging setup**, configure the provider fields: + | Artemis field | What it controls | + |---|---| + | **Genesys Region** | The Genesys Platform API host. A wrong region can authenticate yet fail organization or integration lookups. | + | **Genesys Organization ID** | The organization that owns the integration. Required. | + | **Integration ID** | The Open Messaging integration. Artemis uses it as the external identifier for outbound calls. Required. | + | **Activation Mode** | **Diagnostics only** runs setup checks but doesn't execute live inbound conversations. **Enabled** processes live traffic. **Disabled** turns the adapter off. Start with **Diagnostics only**. | + | **Delivery Mode** | **External bridge** is the standard bot-facing channel. **Agent workflow** makes the connection available to the Genesys Open Messaging agent-transfer handoff. | + | **Genesys Auth Profile** | The active Auth Profile for this organization and environment. Artemis accepts only active Genesys profiles using OAuth client credentials or Bearer authentication. Required. | + | **Webhook Connection Token** | Generated. Routes inbound requests through the webhook URL. Keep the generated value unless an approved migration needs a replacement. | + | **Webhook Signature Secret** | Generated. Verifies the HMAC signature on each inbound request. Keep the generated value unless an approved migration needs a replacement. | - - | Field | Description | - | --- | --- | - | **Environment** | Select an environment to follow its active deployment, or leave the default to use the working copy. | - | **Provider Verification Strength** | **Weak** is the default. Choose **Strong** only for channels or providers whose identity assertions you trust for stronger continuity and linking decisions. | - | **Initial Status** | **Active** connections can be used immediately. **Inactive** connections stay saved but disabled until you activate them. | - +4. Configure the common fields: - - When you create the connection, the platform generates the following values. + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see. Routing ignores it. | + | **Environment** | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | How far the runtime trusts Genesys's identity assertion when it links a user to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | **Active** takes traffic immediately. **Inactive** saves the connection disabled until you activate it. | - | Value | Description | - | --- | --- | - | **Webhook Connection Token** | Identifies the connection and is included in the connection-specific webhook URL. | - | **Webhook Signature Secret** | Verifies incoming webhook requests using HMAC-SHA256. | +5. Select **Create**. +6. Copy the full webhook endpoint and the signature secret from the confirmation screen before you close it. - Copy the generated webhook endpoint and signature secret before closing the confirmation screen. These values are required when configuring the Genesys Open Messaging integration. - - +--- -## Configure the webhook in Genesys Cloud +## Webhook configuration in Genesys - - - In your Genesys Open Messaging integration, enter the complete public HTTPS webhook URL generated for the connection. +Configure the signed webhook in the Open Messaging integration, or let Artemis provision it. - The URL must include the connection token. The generic webhook path cannot identify the required connection. - + + + 1. Paste the full connection-specific HTTPS URL into the Genesys Open Messaging integration. Keep the final connection token. + 2. Enter the Artemis **Webhook Signature Secret** as the integration's outbound webhook signature secret. Don't use the Genesys OAuth client secret or the connection token. + 3. Confirm Genesys signs the exact raw request body with HMAC-SHA256, in a supported header and format. + - - Enter the Webhook Signature Secret generated by the Artemis as the signature secret for the Genesys integration. + + Use this path when the Genesys integration doesn't exist yet. - Do not use the Genesys OAuth client secret or the Webhook Connection Token as the signature secret. - + 1. Verify the region, organization, Auth Profile, connection token, and signature secret on the connection. + 2. On the **Testing** tab, run the provisioning action. Artemis creates the Genesys Open Messaging integration with the current webhook URL and signature secret. + + - - Incoming requests must be signed using **HMAC-SHA256** over the exact raw request body. Runtime validates the signature before processing the request. +Artemis accepts these signature headers and formats. The digest must cover the original request bytes before any JSON parsing or normalization. - Do not parse and reserialize the request body before signature validation because changing the request bytes can cause a valid signature to fail. - - +| Accepted headers | Accepted formats | +|---|---| +| `X-Hub-Signature-256`, `X-Genesys-Signature-256`, `X-Genesys-Signature`, `X-Signature-256`, `X-Signature` | `sha256=`, raw lowercase ``, or `base64` | -## Test the connection +--- -Once the channel is created, select it, then go to the **Testing** tab. +## Validate and enable - - - Open the connection's testing or diagnostics area and run the signature validation. This confirms that the configured signature secret and supported signature format are correct. - +Run every check in diagnostics mode, then switch to live traffic. - - Run the inbound message diagnostic and confirm that Runtime resolves the connection and processes the incoming message correctly. - +1. Open the connection's **Testing** tab and run the signature check on a signed fixture. This confirms the stored secret and signature format without sending provider traffic. +2. Run the inbound diagnostic. Confirm the adapter resolves the connection through the project runtime, normalizes the sender and conversation, and returns redacted provider metadata. +3. Run the receipt diagnostic. Confirm the Auth Profile obtains a token and calls the Genesys receipt endpoint for the configured Integration ID. +4. Change **Activation Mode** to **Enabled**, and confirm the connection status is **Active**. +5. Send a unique live text, a quick reply, and a follow-up in the same Genesys conversation. - - Run the receipt diagnostic to confirm that the Auth Profile can authenticate and communicate with the configured Genesys receipt endpoint. - +--- - - After all diagnostics pass, change **Activation Mode** to **Enabled**. Test a live message, a quick reply, and a follow-up message in the same Genesys conversation. - - +## Messaging and delivery behavior + +Artemis applies these rules to every Open Messaging conversation. + +| Area | Behavior | +|---|---| +| Delivery | Asynchronous. Artemis authenticates and accepts each event, then sends the agent's reply through the Genesys Platform API. | +| Continuity | The Genesys conversation ID is the preferred key. Without it, Artemis falls back to the sender identity and hashes the session components. | +| Quick replies | Artemis sends authored quick replies through the Genesys structured-response endpoint. Return the selected payload unchanged. | +| Receipts | The adapter can send `DELIVERED` and `READ` receipts when the event and integration support them. | +| Media | The default mode is `metadata_only`. Artemis validates and summarizes media references, and downloads binary media only with an explicitly supported mode and allowlist. | +| Payload size | 65,536 bytes per inbound request by default. | + +--- + +## Security and operational boundaries + +The connection depends on a hashed token, an encrypted secret, and an Auth Profile. + +- **Preserve raw bytes**: Pass the raw HTTP request through your ingress proxy unchanged. Re-serialized JSON changes the HMAC input and fails valid signatures. +- **Unique values per environment**: Use separate connection tokens and signature secrets for each environment. Never put OAuth client secrets in the webhook URL, or reuse the signature secret as an OAuth credential. +- **Credentials stay in the Auth Profile**: Keep Genesys OAuth credentials in the bound Auth Profile. Diagnostic and runtime responses redact provider metadata and never expose tokens or secrets. +- **Narrow media allowlists**: Reject oversized bodies before execution, and keep media host allowlists narrow when you enable downloads. + +--- ## Manage the channel connection -Opening a connection from **Deployments** -> **Channels** -> **MESSAGING** -> **Genesys Open Messaging** shows six tabs: **Overview**, **Credentials**, **Configuration**, **Deployment**, **Testing**, and **Activity**. +Open a connection from **Deployments** -> **Channels** -> **Genesys Open Messaging** to manage it. The page has a header, its tabs, and a summary panel on the right. - - - The **Connection Summary** shows these fields. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | --- | --- | - | **Status** | For example: *Active* | - | **Created** | Timestamp the channel was created | - | **Updated** | Timestamp of the last change | - | **Environment** | For example: `staging` | - | **Source Type** | `Channel Connection` | - | **Source ID** | Unique channel identifier (UUID) | - | **Integration ID** | The bound Open Messaging Integration ID, shown for reference. | - - Under **Setup Instructions**, the tab shows the connection-specific webhook endpoint to paste into the Genesys Open Messaging integration. - +**Summary panel.** Stays visible on every tab and shows the channel, connection type, identifier, credential status, webhook endpoint, and creation and update times. + - Credentials are saved and encrypted after creation; fields show placeholder text and accept new values only if you want to update them. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value. | Field | Description | - | --- | --- | - | **Use Auth Profile** | Toggle on to authenticate through a saved Auth Profile. | - | **Genesys Auth Profile** | Picker to select or change the bound Auth Profile. | - | **Webhook Signature Secret** | Shown as *(saved — enter to update)*; leave blank to keep the current value. | + |---|---| + | **Use Auth Profile** | Authenticates outbound calls through a saved Auth Profile. | + | **Genesys Auth Profile** | Selects or changes the bound Auth Profile. | + | **Webhook Signature Secret** | Replace it here and in the Genesys integration together. | - The **Webhook Connection Token** isn't editable here — it's embedded in the webhook URL and can't be changed after creation. To rotate it, create a new connection. - - Select **Save** to apply any changes. + You can't edit the **Webhook Connection Token**, because the webhook URL embeds it. To replace it, create a new connection. Select **Save Credentials** to apply your changes. - | Field | Description | - | --- | --- | - | **Display Name** | The connection's label. | - | **Provider Verification Strength** | **Weak** or **Strong** — see [Complete common connection settings](#integrate-the-genesys-open-messaging-connection). | - | **Integration ID** | The bound Open Messaging Integration ID. | + Update the connection's behavior. - Select **Save Changes** to apply any changes. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Genesys's identity assertion. | + | **Integration ID** | The bound Open Messaging integration. | + | **Activation Mode** | Switch from **Diagnostics only** to **Enabled** after validation. | + + Select **Save Changes** to apply your changes. - | Field | Description | - | --- | --- | - | **Environment** | Selects which deployed version handles incoming messages. | - | **Active Deployment** | Shows the bound deployment version and date, or a **Working Copy** warning if nothing has been deployed to this environment yet. | + Choose which deployed version answers messages. - Select **Save Changes** after switching the environment or version. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it, or a **Working Copy (draft)** warning. | + + Select **Save Changes** after you switch the environment. - The **Diagnostics** panel runs the checks described in [Test the connection](#test-the-connection). + The **Diagnostics** panel runs the checks in [Validate and enable](#validate-and-enable). + + | Control | Description | + |---|---| + | **Endpoint**, **Signature Secret** | The webhook under test and the secret that signs the test request. | + | **Customer ID**, **Message**, **Originating Message ID** | The test conversation inputs. | + | **Run Signature**, **Run Inbound**, **Run Receipt** | Run each diagnostic. | + | **Last Success**, **Last Failure** | The most recent diagnostic outcomes. | + + The **Validation Evidence** panel records the results of those runs. + + | Group | Fields | + |---|---| + | Status | **Validated At**, **Status**, **Summary**, **Automated Provisioning Verified** | + | Diagnostics | **Signature Diagnostic ID**, **Inbound Diagnostic ID**, **Receipt Diagnostic ID**, **Trace Count**, **Runtime Trace IDs** | + | Conversation | **Delivery Mode**, **Provider Conversation ID**, **Sandbox Evidence References** | + | Performance | **Max Concurrent Sessions**, **Chat Round Trip P95 ms**, **Packet Loss Percent** | + | Operations | **Operator Runbook Reference**, **Operator Dashboard Reference**, **Operator Alert Reference** | + + - | Field | Description | - | --- | --- | - | **Last Success** / **Last Failure** | Timestamps of the most recent diagnostic outcomes. | - | **Endpoint** | The webhook endpoint under test. | - | **Signature Secret** | The secret used to sign the test request. | - | **Customer ID** | The test conversation's customer identifier. | - | **Message** | The test message body. | - | **Originating Message ID** | The test message's originating ID. | - | **Run Signature** | Runs the webhook signature validation. | - | **Run Inbound** | Runs the inbound message diagnostic. | - | **Run Receipt** | Runs the delivery or read receipt diagnostic. | - - The **Validation Evidence** panel records the results and supporting evidence from those runs. +--- - | Field | Description | - | --- | --- | - | **Validated At** | Timestamp of the last passing validation. | - | **Trace Count** | Number of Runtime traces captured during validation. | - | **Status** | Overall validation status. | - | **Operator Runbook Reference** | Link or ID for the operator runbook used during validation. | - | **Operator Dashboard Reference** | Link or ID for the operator's monitoring dashboard. | - | **Operator Alert Reference** | Link or ID for the operator's alert configuration. | - | **Runtime Trace IDs** | Trace IDs captured during validation runs. | - | **Sandbox Evidence References** | Links or IDs for sandbox test evidence. | - | **Summary** | Free-text summary of the validation outcome. | - | **Max Concurrent Sessions** | Peak concurrent sessions observed during validation. | - | **Packet Loss Percent** | Observed packet loss during validation, if applicable. | - | **Delivery Mode** | The delivery mode validated (for example, External bridge). | - | **Provider Conversation ID** | The Genesys conversation ID used during validation. | - | **Signature Diagnostic ID** / **Inbound Diagnostic ID** / **Receipt Diagnostic ID** | IDs referencing each diagnostic run. | - | **Automated Provisioning Verified** | Whether automated provisioning was confirmed during validation. | - | **Chat Round Trip P95 ms** | The 95th-percentile round-trip latency observed during validation. | - - \ No newline at end of file +## Troubleshoot connection issues + +Most failures trace to the signature, the activation mode, or the Auth Profile. + +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Connection not found | Generic path, lost token, or deleted connection | Use the full connection-specific URL through the correct project runtime, and confirm the connection still exists. | +| Webhook returns `401` | Signature mismatch | Confirm Genesys signs the exact raw body with the matching secret, in a supported header and format, and that the ingress proxy doesn't rewrite the body. | +| Diagnostics pass but Artemis ignores live messages | The adapter is still in diagnostics mode | Change **Activation Mode** to **Enabled**, and confirm the connection status is **Active**. | +| Inbound succeeds but replies fail | The Auth Profile can't reach the integration | Confirm the Auth Profile is active, uses connector `genesys`, targets the same region and organization, and can call the configured Integration ID. | +| Conversation context resets | The conversation ID changes | Make sure Genesys sends a stable conversation ID for follow-up turns, not a per-message identifier. | +| Text works but attachments don't | Default `metadata_only` media mode | Check media rejection reasons, allowed host suffixes, reference count, and payload size limits before you enable downloads. | + +{{related}} + +- [Channels](/agent-platform/channels) +- [Set up Genesys](/agent-platform/channels/genesys) +- [Set up Zendesk](/agent-platform/channels/zendesk) \ No newline at end of file diff --git a/agent-platform/channels/genesys.mdx b/agent-platform/channels/genesys.mdx index d399f1b0a..c7ffa9367 100644 --- a/agent-platform/channels/genesys.mdx +++ b/agent-platform/channels/genesys.mdx @@ -3,86 +3,72 @@ title: Set up Genesys sidebarTitle: Genesys --- -[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect your agent to Genesys Cloud as a Bot Connector so an Architect message flow can hand a conversation to it for intent and slot processing. You install the Bot Connector integration in Genesys, bind its Stream ID and shared secret to Artemis, then call the integration from an Architect flow. - -This channel works differently from every other messaging channel. Genesys sends one authenticated POST carrying the user's turn and holds that request open while your agent runs, then reads the reply out of the same HTTP response. There's no callback and no later send API. +Connect your agent to Genesys Cloud as a Bot Connector, so an Architect flow hands each conversation turn to it. You install the Bot Connector integration in Genesys, bind its Stream ID and a shared secret to Artemis, then call the integration from an Architect flow. The setup requires: -1. [Genesys Cloud setup](#genesys-cloud-setup): install and name the Bot Connector integration, and note its Stream ID. -2. [Artemis channel configuration](#artemis-channel-configuration) using the Stream ID and a shared secret you generate, then copy the generated Bot Connector URL. -3. [Bot Connector configuration in Genesys](#bot-connector-configuration-in-genesys): set that URL and the same secret on the integration, activate it, and call it from an Architect flow. +1. [Genesys Cloud setup](#genesys-cloud-setup): install the Bot Connector integration and copy its Stream ID. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +3. [Bot Connector configuration in Genesys](#bot-connector-configuration-in-genesys): set the URL and secret, activate the integration, and call it from Architect. +4. [Verify the connection](#verify-the-connection) end to end. -After you complete the configuration, an Architect flow reaching the **Call Bot Connector** action sends the turn to Artemis, the bound deployment answers inside the same request, and Architect branches on the intent your agent returns. +After setup, an Architect flow that reaches **Call Bot Connector** sends the turn to Artemis. The agent answers inside the same HTTP request, and Architect branches on the returned intent. **Important considerations** -- **The response travels in the same request**: Genesys waits for your agent. Provider timeout and agent execution time have to be compatible, and this channel stays non-streaming by design. -- **Client Secret isn't a Genesys OAuth secret**: for Bot Connector, it's a pre-shared bearer token you invent and configure identically on both sides. Substituting an OAuth integration secret fails unless Genesys sends that same value on the webhook request. -- **Bot Connector needs a subscription change**: Genesys requires you to contact Genesys Cloud Sales before you can install the integration. -- **Architect intents must already exist**: Artemis returns intent names that Genesys matches to branches in your flow. It doesn't create or validate them, so a name that doesn't exist in Architect produces a branch that never fires. +- **The response travels in the same request**: Genesys holds one POST open while the agent runs, then reads the reply from that response. There's no callback or later send API, so the channel stays synchronous and non-streaming. +- **Client Secret isn't a Genesys OAuth secret**: It's a pre-shared ingress token you generate and enter identically on both sides. An OAuth integration secret fails unless Genesys sends that same value on webhook requests. +- **Bot Connector needs a subscription change**: Contact Genesys Cloud Sales before you can install the integration. Genesys allows up to five Bot Connector integrations per organization. +- **Architect intents must already exist**: Artemis returns intent names that Architect matches to branches. Artemis doesn't create or validate them. ## Prerequisites -- A Genesys Cloud organization with the Bot Connector integration available on your subscription, in the region that owns the Architect flow. -- Admin access in Genesys Cloud, with permission to install integrations and edit Architect flows. -- An Architect message flow where the conversation should reach the agent, or permission to create one. +Confirm these before you start. + +- A Genesys Cloud organization with Bot Connector on its subscription, in the region that owns the Architect flow. +- Genesys Cloud admin access, with permission to install integrations and edit Architect flows. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- -## How Artemis handles Bot Connector requests - -Genesys posts to a URL ending in the Stream ID, so Artemis resolves the connection from that path segment and the conversation from the payload. +## How Artemis routes Bot Connector requests -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Stream ID** | Genesys | Routes inbound requests. Artemis reads the final path segment and matches it to an active connection. It's a routing identifier rather than a secret. | -| **Client Secret** | You | Authenticates the request. Artemis compares the token Genesys sends with the stored secret using a timing-safe check. | -| Genesys conversation ID | Genesys | Identifies each end-user session inside the connection. Artemis keys the session to it, so reusing it continues the conversation and changing it starts a new one. | -| **Webhook URL** | Artemis | Receives the Bot Connector POST. It ends with the encoded Stream ID, and the generic Genesys route alone can't select a connection. | +Genesys posts to a URL that ends with the Stream ID. Artemis resolves the connection from that path segment and the session from the payload. -Because the exchange is synchronous, the HTTP response carries everything Genesys needs: the reply messages, the bot state, the intent, and whether the task ended. Nothing arrives later. +| Piece | Owner | What it does | +|---|---|---| +| **Stream ID** | Genesys | Routes requests. Artemis reads the final `/hooks/{streamId}` path segment and matches it to an active connection. It's a routing identifier, not a secret. | +| **Client Secret** | You | Authenticates each request. Artemis compares the received token with the encrypted secret using a timing-safe check. | +| `genesysConversationId` | Genesys | Identifies each end-user session inside the connection. Reusing it continues the conversation, and changing it starts a new one. | +| **Webhook URL** | Artemis | Receives the Bot Connector POST. It ends with the encoded Stream ID. | --- ## Genesys Cloud setup -Do this work in Genesys Cloud before you open Artemis. Genesys documents the same screens in [Configure the Genesys Bot Connector integration](https://help.genesys.cloud/articles/configure-the-genesys-bot-connector-integration/). +Do this in Genesys Cloud before you open Artemis. Select **Open Genesys Cloud** in the setup guide to jump straight there. Genesys documents the same screens in [Configure the Genesys Bot Connector integration](https://help.genesys.cloud/articles/configure-the-genesys-bot-connector-integration/). - - Sign in to the Genesys Cloud organization and regional domain that own the Architect flow you intend to change. - - Genesys organizations are region-specific, so a development organization's integration pointed at production Artemis produces a setup that looks correct but serves the wrong traffic. Confirm the organization before you install anything. + + Sign in to the organization and regional domain that own the Architect flow. Don't point a development organization's integration at production Artemis. - 1. Select **Admin**, then under **Integrations**, select **Integrations**. On newer navigation, select **Menu** -> **IT and Integrations** -> **Integrations**. - 2. Search for the **Genesys Bot Connector** tile and click **Install**. - 3. On the **Details** tab, give the integration a name that identifies the agent and the environment, and add notes if your team uses them. - - Pick a distinct name. Architect actions reference integrations by name, so duplicates make it easy to point a flow at the wrong one later. + 1. Go to **Admin** -> **Integrations** -> **Integrations**. On newer navigation, go to **Menu** -> **IT and Integrations** -> **Integrations**. + 2. Find the **Genesys Bot Connector** tile and select **Install**. + 3. On the **Details** tab, name the integration for the agent and environment. - Don't install the **Genesys Digital Bot Connector** tile by mistake. It's a separate integration with its own Architect action, and Artemis connects through Bot Connector. Keep this integration's lifecycle separate from Open Messaging and Audio Connector integrations too. - - Genesys allows up to five Bot Connector integrations per organization, which is the practical ceiling on how many Artemis connections one organization can carry. + Don't install **Genesys Digital Bot Connector**. It's a separate integration with its own Architect action. Keep this integration separate from Open Messaging and Audio Connector integrations too. - Copy the Stream ID Genesys shows for this integration, exactly as it appears. - - This becomes the routing identifier in Artemis and the last segment of the webhook URL. Copy it without surrounding whitespace, because a trailing space produces a 404 that looks like a missing connection. - - Don't substitute the Genesys organization ID, the integration ID, an OAuth client ID, a conversation ID, or the Architect flow ID. None of them route. + Copy the Bot Connector Stream ID exactly, with no surrounding whitespace. It becomes the routing identifier in Artemis and the last segment of the webhook URL. - Create a high-entropy random string. You invent this value rather than Genesys issuing it, and you'll enter the identical string in two places: the Artemis connection, and the Bot Connector credentials in Genesys. - - Use a different secret per environment, and store it in your secret manager. This token is the only thing standing between the public URL and your agent. + Create a high-entropy random string, and store it in your secret manager. Use a different secret per environment. @@ -90,197 +76,188 @@ Do this work in Genesys Cloud before you open Artemis. Genesys documents the sam ## Artemis channel configuration -Create the connection before you configure the integration in Genesys. Artemis resolves the Stream ID and decrypts the secret before it authenticates a request, so an inactive or missing connection returns 404 even when the URL is right. +Create the connection before Genesys sends its first request. Artemis must resolve the Stream ID and the encrypted secret before it can authenticate and run a request. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **Genesys** -> **+ New**. -3. Configure the following fields: - - | Artemis connection field | Source / Notes | - |---|---| - | Display Name | The label operators see in the connections list. Name it for the Genesys organization and the environment it serves, because a project can hold several Genesys connections. Routing ignores this value. | - | Stream ID | The routing key. Artemis writes it into the webhook path and resolves the connection from it. Enter the exact value from the Bot Connector integration, with no leading or trailing whitespace. | - | Client Secret | The shared bearer token you generated. Artemis compares the token on each request with this encrypted value using a timing-safe check. | - | Environment | The published environment whose active deployment answers the Architect flow. Leave the working copy default only while you develop. | - | Provider Verification Strength | How far Artemis trusts Genesys's identity assertion when it links a caller to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Whether the connection handles requests. Set it to **Active**, because an inactive connection returns 404 rather than an authentication error, which sends you looking in the wrong place. | - -4. Click **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab.
- The URL ends with the URL-encoded Stream ID. Copy the whole thing, because the generic Genesys route can't identify which connection a request belongs to. +2. Go to **Deployments** -> **Channels** -> **Genesys** -> **+ New**. The **New Genesys Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: -### Validation checklist + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see. Name it for the Genesys organization and environment. Routing ignores it. | + | **Stream ID** | The Bot Connector integration | The routing key. Don't enter the organization ID, integration ID, OAuth client ID, conversation ID, or Architect flow ID. | + | **Client Secret** | The token you generated | Authenticates each request. Enter the same value in the Genesys integration. | + | **Environment** | Your published environments | The environment whose active deployment answers the Architect flow. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Genesys's identity assertion when it links a user to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | Keep it **Active**. An inactive connection returns not found even when the URL is right. | -| Validation item | Expected result | -|:---|:---| -| Confirm the subscription | The Genesys Bot Connector tile appears in your organization's integration list. | -| Install the integration | Bot Connector integration installed and named distinctly, in the region that owns the flow. | -| Copy the Stream ID | Stream ID copied exactly, with no surrounding whitespace, and distinct from organization, integration, and flow IDs. | -| Create the Artemis connection | Connection saved as Active with the Stream ID and the shared secret. | -| Copy the webhook URL | Bot Connector URL copied from the **Overview** tab, ending with the encoded Stream ID. | -| Configure the integration | URL and matching secret saved on the integration, and its status set to active. | -| Map the Architect outcomes | Intent names in Artemis match branches that already exist in the Architect flow. | -| Wire the Architect action | **Call Bot Connector** action added to the flow, pointing at this integration, with its failure path connected. | -| Run a test interaction | Test turn reaches the agent and Architect branches on the returned intent. See [Verify the connection](#verify-the-connection). | +4. Select **Create**. +5. Open the connection and copy the **Webhook URL** from the summary panel. Keep the encoded Stream ID at the end. The generic `/genesys/hooks` path can't select a connection. --- ## Bot Connector configuration in Genesys -Return to the integration you installed and finish it with the URL and secret from Artemis, then call it from a flow. +Return to the integration and finish it with the Artemis values, then call it from a flow. - Open the integration's **Configuration** tab and set the Bot Connector URL to the **Webhook URL** from the Artemis connection. - - Preserve the encoded Stream ID at the end. Genesys uses this URL to relay each utterance, so a truncated path reaches Artemis and resolves to nothing. + On the integration's **Configuration** tab, set the Bot Connector URL to the Artemis **Webhook URL**. Use the public HTTPS runtime origin. - - Open the integration's **Credentials** tab and configure the same Client Secret you entered in Artemis as the bearer token. + + On the **Credentials** tab, enter the same Client Secret as the bearer token. - Artemis prefers the token on an `Authorization: Bearer` header. It also accepts `x-channel-secret`, `x-ingress-secret`, or `x-webhook-secret`. It never accepts a token in the query string, so don't append one to the URL. + | Header | Use | + |---|---| + | `Authorization: Bearer` | Preferred | + | `x-channel-secret`, `x-ingress-secret`, `x-webhook-secret` | Also accepted | + + Artemis never accepts a token in the query string. - Set the integration status to active. - - An inactive integration doesn't appear in Architect at all, so this step has to come before you try to add the action. + Set the integration status to active. An inactive integration never appears in Architect. - - 1. Open the Architect message flow that should reach the agent. - 2. From the toolbox, drag a **Call Bot Connector** action into the flow. - 3. Set the action's bot integration to the integration you just configured, and set the name and version fields the action asks for. - 4. Connect the action's failure path to real handling rather than leaving it unconnected. + + 1. Open the Architect flow that should reach the agent. + 2. Add or select a **Call Bot Connector** action, and point it at this integration. + 3. Connect the failure path to real handling. - Genesys documents the action's inputs, timeouts, and error types in [Call Bot Connector action](https://help.genesys.cloud/articles/call-bot-connector-action/). The failure path matters: Architect takes it on execution errors and connectivity problems, and it also takes a safety path after four consecutive turns return an unchanged intent. + Architect takes the failure path on execution and connectivity errors, and after four consecutive turns return an unchanged intent. See [Call Bot Connector action](https://help.genesys.cloud/articles/call-bot-connector-action/). - Run Architect's validation and test the flow on a non-production interaction. - - Publish only after you've confirmed the URL, the secret, the response timing, and the failure branches. A published flow with an unreachable bot fails in front of customers. + Run Architect validation and test on a non-production interaction. Publish only after you confirm the URL, secret, response timing, and failure branches. +### Validation checklist + +Work down this list once per connection. + +| Validation item | Expected result | +|:---|:---| +| Install the integration | Bot Connector installed and named distinctly, in the region that owns the flow. | +| Create the Artemis connection | Saved as **Active** with the exact Stream ID and the shared secret. | +| Configure the integration | Webhook URL and matching secret saved, and the integration active. | +| Map the Architect outcomes | Intent names match branches that exist in the flow. | +| Wire the Architect action | **Call Bot Connector** points at this integration, with the failure path connected. | +| Run a test interaction | A turn reaches the agent, and Architect branches on the returned intent. | + --- ## Map Architect outcomes -Artemis returns an intent name to Genesys at the end of each turn, and Architect branches on it. Configure the mapping on the connection's **Configuration** tab, under **Architect outcome mapping**. +Artemis returns an intent name with each reply, and Architect branches on it. Configure the mapping on the **Configuration** tab under **Architect outcome mapping**. -Turn on **Enable terminal intent mapping**, then set the intent name Artemis returns for each outcome. +1. Turn on **Enable terminal intent mapping**. +2. For each outcome, select a **Value source** and enter the **Genesys Architect intent name**. +3. Select **Save Changes**. -| Outcome | Artemis returns it when | -| ------- | ----------------------- | -| Continue conversation | The conversation should stay with this agent for another turn. | -| Escalate to an agent | The conversation should transfer to a human. | -| Close the session | The conversation should end. | +| Outcome | When Artemis returns the intent | +|---|---| +| **Continue conversation** | On ongoing replies 1, 4, 7, and every third reply after that. Other ongoing replies omit the intent. | +| Escalate to an agent | On any turn that escalates. | +| Close the session | On any turn that ends the session. | -Each outcome takes a **Value source** of either a literal intent name you type, or a project variable that supplies it. Use a project variable when the same agent serves several Genesys flows with different intent vocabularies, and a literal name otherwise. +**Value source** takes a literal intent name or a project variable. Use a project variable when one agent serves several flows with different intent names. Only non-secret project variables qualify. Select **Open project variables** to create one. -These names have to match intents and branches that already exist in your Architect flow. Artemis neither creates nor validates them, so a typo produces a branch Architect never takes rather than an error you can see. Agree the names with whoever owns the flow before you enter them here. +Matching intents and Architect branches must already exist in Genesys Cloud. A typo produces a branch Architect never takes, without an error. --- ## Verify the connection -Test each failure mode as well as the happy path, because Architect's branching depends on Artemis returning the right status for each one. +Test the failure modes as well as the happy path, because Architect branches on the status Artemis returns. -1. Send a text turn with a unique message and a stable Genesys conversation ID.
- Confirm an HTTP 200 and one text reply in the response. -2. Send a second turn reusing the same conversation ID, and confirm it resumes the same session.
- A different conversation ID should open a separate session. -3. Return an authored quick reply, send its encoded payload back as the button response, and confirm the session resumes with the action value you authored. -4. Send a request with the wrong secret and confirm it returns 401. -5. Send a request to an unknown or inactive Stream ID and confirm it returns 404. -6. Send malformed input and confirm it returns 400. -7. Confirm the Architect flow handles a 503 busy response and an execution failure without looping. +1. Send `inputMessage.type=Text` with a unique message and a stable `genesysConversationId`. Confirm HTTP `200` and one Text reply in `replymessages`. +2. Send a second turn with the same `genesysConversationId`. Confirm it resumes the same `genesys:{conversationId}` session, and that a different ID starts a new one. +3. Return an authored button, send its encoded payload in `inputMessage.buttonResponse.payload`, and confirm the session resumes with the right action value. +4. Confirm a wrong secret returns `401`, an unknown or inactive Stream ID returns `404`, and malformed input returns `400`. +5. Confirm the Architect flow handles `503` busy and execution failures without looping. --- ## Request and response contract -Genesys carries the whole turn in one exchange, so both halves have required fields. - -| Direction | Required content | -| --------- | ---------------- | -| Request | A non-empty Genesys conversation ID and an input message type. A text turn also needs the message text; a structured quick reply needs the button response payload. | -| Response | The reply messages, the bot state, the intent name, and whether the task ended. Genesys reads all of these from the same HTTP response. | +Genesys carries the whole turn in one exchange. -Keep the conversation ID stable across every turn in one Genesys interaction. Replacing it with the Stream ID or an ephemeral request ID resets the conversation context, which looks like the agent forgetting rather than like a configuration error. - -Optional session metadata crosses a trust boundary, so Artemis validates it before the agent runs. Send it only in the JSON object shape Artemis expects. +| Direction | Content | +|---|---| +| Request | Always `genesysConversationId` and `inputMessage.type`. Text turns add `inputMessage.text`. Structured quick replies add `inputMessage.buttonResponse.payload`. | +| Response | `replymessages`, `botState`, `intent`, and `endOfTask`. A normal reply carries one `replymessages` entry of type Text. | +| Quick replies | Authored buttons become a Structured reply with QuickReply entries. Each payload encodes the action ID and value. | +| Defaults | `botState` `MOREDATA`, intent `Default Kore VA Intent`, and `endOfTask` `false`, unless outcome mapping applies. | +| Media | The channel doesn't process inbound media or send media responses. | --- -## Secure the connection - -The Stream ID appears in a public URL and isn't a secret. HTTPS and the shared token protect the endpoint, so never put the token in the URL or in logs. - -Use a unique, high-entropy Client Secret for each environment, stored only in the Genesys integration's secure credential configuration and in encrypted Artemis credentials. Rotating it means changing both sides together, because Artemis rejects a request the moment the values diverge. +## Security and operational boundaries -Prefer the `Authorization: Bearer` header. If your ingress adds or rewrites headers, make sure it preserves the one Genesys sends and strips any untrusted duplicate before the request reaches Artemis. Two competing authorization headers produce a 401 that looks like a wrong secret. +HTTPS and the shared token protect the endpoint. -Use separate Genesys integrations, Stream IDs, secrets, Architect flows or versions, and connections for development and production. +- **Secret per environment**: Use a unique, high-entropy Client Secret for each environment. Store it only in the Genesys integration's credentials and in Artemis. +- **One authorization header**: Prefer `Authorization: Bearer`. If your ingress uses another supported header, make sure it preserves that header and strips untrusted duplicates. +- **Stream ID is public**: Treat it as a routing value. Never put the token in the URL or in logs. +- **Session metadata**: Optional `sessionMetadata` crosses a trust boundary, and Artemis validates it before the agent runs. Send only the expected JSON object shape. +- **Separate environments**: Use separate integrations, Stream IDs, secrets, Architect flows or versions, and connections for development and production. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **Genesys** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles requests. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers requests. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to configure in Genesys and the **Stream ID** it ends with, each with a copy control. Compare the Stream ID here with the integration's whenever requests return 404. - +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Genesys** and **Channel Connection**. | +| **Identifier** | The Stream ID this connection routes on. Compare it with the integration's Stream ID when requests return `404`. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The Bot Connector URL for Genesys, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + - Artemis encrypts the secret after you save it, so the field reads as saved rather than showing its value. Leave it empty to keep the current value, or enter a new one to replace it. + Artemis encrypts the secret after you save it. Leave the field blank to keep the current value, or enter a new one to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credential from a saved auth profile instead of the field below. Prefer it when the same secret serves more than one connection, since a rotation then touches one profile. | - | **Client Secret** | The shared bearer token. Change it here and in the Genesys integration as one coordinated step, because the two have to match on every request. | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the field below. | + | **Client Secret** | The shared token. Change it here and in the Genesys integration together, because Artemis rejects requests as soon as the values differ. | - Click **Save Credentials** to apply your changes. + Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this organization changes. - - Under **Genesys Settings**, **Stream ID** appears read-only. The webhook URL is built from it, so changing it would invalidate the URL configured in Genesys. Create a new connection to serve a different integration. - - **Authorization Message** controls what the customer sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. + Update how the connection behaves. **Genesys Settings** holds the provider-specific fields. - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | - - **Architect outcome mapping** sets the intent names Artemis returns to Genesys. See [Map Architect outcomes](#map-architect-outcomes). - - Click **Save Changes** to apply your changes. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Genesys's identity assertion. | + | **Stream ID** | Read-only, with a copy control. To serve a different integration, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The Bot Connector URL, with a copy control. | + | **Architect outcome mapping** | The intent names Artemis returns. See [Map Architect outcomes](#map-architect-outcomes). | + + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers requests on this connection. + Choose which deployed version answers the Architect flow. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic and when someone deployed it. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Check this pair when the flow reaches the agent but the agent behaves like an older build. The connection follows whatever the environment currently has deployed, not the version you last edited. Click **Save Changes** after you switch. + Select **Save Changes** after you switch the environment. @@ -288,32 +265,35 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Match the status code first. Most failures trace to the Stream ID, the secret, or the conversation ID. + | Symptom | Likely cause | Recommended action | |---|---|---| -| The webhook returns 404 | The Stream ID doesn't match, or the connection isn't active | Confirm the URL ends with the exact Stream ID, check the saved identifier for copied whitespace, and confirm the connection is Active in the intended project. | -| The webhook returns 401 | The token doesn't match, or headers conflict | Send the exact Client Secret through `Authorization: Bearer` or a supported secret header, remove duplicate authorization headers at your ingress, and confirm nobody rotated the secret on one side only. | -| The webhook returns 400 | The request is missing a required field | Include a non-empty conversation ID and an input message type. Text turns also need the message text, and structured actions need the button response payload. | -| The webhook returns 503 busy | Concurrent turns for the same session couldn't acquire the lock | Serialize turns within a conversation and retry according to the Architect failure policy. | -| Genesys times out before a response | Agent execution outlasts the provider timeout | Compare the configured timeout with actual execution duration, investigate model and tool latency, and keep this channel synchronous and non-streaming. | -| Text works but quick replies don't | The response lacks structured entries, or the payload doesn't return | Confirm the response carries quick reply entries and that the selected encoded payload comes back as the button response payload. | -| Conversation context resets between turns | The conversation ID changes each turn | Preserve the same Genesys conversation ID for every turn in one interaction, and don't replace it with the Stream ID or a per-request identifier. | -| Architect never takes the expected branch | The intent name doesn't exist in the flow | Compare the names in **Architect outcome mapping** with the intents and branches in Architect. Artemis doesn't create or validate them. | -| The integration doesn't appear in Architect | The integration isn't active | Set the integration's status to active in Genesys Cloud, then reopen the flow. | +| Webhook returns `404` | Stream ID mismatch, or the connection isn't active | Confirm the URL ends with the exact Stream ID, check for copied whitespace, and confirm the connection is **Active** in the intended project. | +| Webhook returns `401` | Token mismatch or conflicting headers | Send the exact Client Secret through `Authorization: Bearer` or a supported header, remove duplicate auth headers, and confirm nobody rotated the secret on one side only. | +| Webhook returns `400` | A required field is missing | Include a non-empty `genesysConversationId` and `inputMessage.type`. Text turns need `inputMessage.text`, and Structured actions need `buttonResponse.payload`. | +| Webhook returns `503` busy | Concurrent turns for one session | Serialize turns within a conversation, and retry according to the Architect failure policy. | +| Genesys times out before a response | Agent execution outlasts the provider timeout | Compare the provider timeout with execution duration, and check model and tool latency. | +| Text works but quick replies don't | Missing QuickReply entries or a lost payload | Confirm the response contains Structured QuickReply entries and that the encoded payload returns as `buttonResponse.payload`. | +| Conversation context resets | The conversation ID changes between turns | Keep the same `genesysConversationId` for every turn, and never replace it with the Stream ID or a request ID. | +| Architect never takes the expected branch | The intent name doesn't exist in the flow | Compare **Architect outcome mapping** with the intents and branches in Architect. | +| The integration doesn't appear in Architect | The integration isn't active | Activate it in Genesys Cloud, then reopen the flow. | --- ## Genesys reference -Use these Genesys pages when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. | Resource | Use it for | -| -------- | ---------- | -| [About Genesys Bot Connector](https://help.genesys.cloud/articles/about-genesys-bot-connector/) | What the connector supports, including quick replies, cards, and carousels. | -| [Configure the Genesys Bot Connector integration](https://help.genesys.cloud/articles/configure-the-genesys-bot-connector-integration/) | Installing the integration, its tabs, and activating it. | -| [Call Bot Connector action](https://help.genesys.cloud/articles/call-bot-connector-action/) | Action inputs, response timeouts, session variables, error types, and failure paths. | -| [About Genesys Digital Bot Connector](https://help.genesys.cloud/articles/about-genesys-digital-bot-connector/) | Telling the two connectors apart, if you're unsure which one your flow uses. | +|---|---| +| [About Genesys Bot Connector](https://help.genesys.cloud/articles/about-genesys-bot-connector/) | What the connector supports. | +| [Configure the Genesys Bot Connector integration](https://help.genesys.cloud/articles/configure-the-genesys-bot-connector-integration/) | Installing and activating the integration. | +| [Call Bot Connector action](https://help.genesys.cloud/articles/call-bot-connector-action/) | Action inputs, timeouts, error types, and failure paths. | +| [About Genesys Digital Bot Connector](https://help.genesys.cloud/articles/about-genesys-digital-bot-connector/) | Telling the two connectors apart. | {{related}} -- [Set up Zendesk](/agent-platform/channels/zendesk) -- [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file +- [Channels](/agent-platform/channels) +- [Set up Genesys Open Messaging](/agent-platform/channels/genesys-open-messaging) +- [Set up Zendesk](/agent-platform/channels/zendesk) \ No newline at end of file diff --git a/agent-platform/channels/instagram.mdx b/agent-platform/channels/instagram.mdx index d69897db0..3dedb1d63 100644 --- a/agent-platform/channels/instagram.mdx +++ b/agent-platform/channels/instagram.mdx @@ -3,115 +3,98 @@ title: Set up Instagram sidebarTitle: Instagram --- -[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect an Instagram professional account to your agent so people reach it through Instagram direct messages. Instagram messaging runs on the Messenger Platform. You prepare a Meta app and a Facebook Page alongside the Instagram account, then register a signed webhook that Meta verifies before it sends anything. +Connect an Instagram professional account to your agent so people reach it through Instagram direct messages. You link the account to a Facebook Page and a Meta app, enter the account's credentials in Artemis, then register a signed webhook that Meta verifies. The setup requires: -1. [Instagram and Meta setup](#instagram-and-meta-setup): Confirm the account is professional, link it to a Facebook Page, add the Instagram product to a Meta app, and collect the account ID, Page Access Token, and App Secret. -2. [Artemis channel configuration](#artemis-channel-configuration) using those values, then copy the generated webhook URL. -3. [Webhook configuration in Meta](#webhook-configuration-in-meta): Verify the callback and subscribe the professional account to the message events. +1. [Instagram and Meta setup](#instagram-and-meta-setup): prepare the account, Page, and app, and collect four values. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +3. [Webhook configuration in Meta](#webhook-configuration-in-meta): verify the callback and subscribe the account. +4. [Verify the connection](#verify-the-connection) with real messages, actions, and media. -After the configuration is complete, a direct message to the professional account opens a session in Artemis, the bound deployment answers it, and the reply returns to the same Instagram conversation. +After setup, a direct message to the professional account opens a session in Artemis, and the agent replies in the same Instagram conversation. **Important considerations** -- **Instagram messaging runs through a Facebook Page**: The Page issues the access token that authorizes outbound replies, so the Instagram account, the Page, the Meta app, the App Secret, and the webhook subscription all have to belong to one linked set. Values from two apps produce failures that look unrelated to each other. -- **Three Meta identifiers compete for one field**: Artemis routes on the Instagram Account ID. The Facebook Page ID, the Meta App ID, and the Instagram-scoped ID that identifies a customer all appear nearby and none of them route. -- **Create the connection before the webhook**: Meta's verification challenge carries the Verify Token but no account ID, so Artemis finds the connection by the stored token. An unsaved connection fails verification. -- **Development mode limits who can test**: Only assigned app roles and eligible testers can exercise the integration until you complete permission review and switch the app to Live. +- **The Instagram Account ID selects the connection**: Artemis reads the account ID from `entry.id` in each signed webhook and matches it to the connection. The linked Page Access Token must message on behalf of that same account. +- **Three IDs look alike**: Artemis routes on the Instagram Account ID. The Facebook Page ID and each customer's sender ID appear nearby and never route. +- **Create the connection before you verify the webhook**: Meta's verification request carries the Verify Token but no account ID, so Artemis finds the connection by the stored token. +- **Development mode limits testing**: Only app roles and Instagram testers reach the agent until you complete review and switch the app to Live. ## Prerequisites -- An Instagram **Business** or **Creator** account. A personal account can't support this integration, and converting it is the first step below. -- A Facebook Page linked to that Instagram account, on which your account can perform the messaging and moderate tasks. Meta requires both tasks of whoever generates the Page Access Token. -- A Meta developer account with permission to create a business app, add the Instagram product, and reveal the App Secret. +Confirm these before you start. + +- An Instagram **Business** or **Creator** account. Personal accounts can't use this integration. +- A Facebook Page linked to that account, where you can perform the messaging and moderate tasks. +- A Meta developer account that can create a business app and reveal its App Secret. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- ## How Artemis routes Instagram events -Meta sends every event for the account to one generic URL, so Artemis identifies the connection from the payload rather than the path. It reads the Instagram account ID out of the signed event and matches it to a connection. +Meta sends every event to one generic URL, so Artemis identifies the connection from the signed payload. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Instagram Account ID** | Meta | Routes inbound events. Artemis reads the account ID from each signed webhook and matches it to this connection. | -| **Page Access Token** | Meta | Authorizes outbound replies. Artemis sends to the account's messages endpoint using it as a bearer token, so the token has to belong to the Page linked to this account and carry the Instagram messaging permission. | -| **App Secret** | Meta | Verifies the `X-Hub-Signature-256` header on every inbound POST. Artemis computes the HMAC over the unchanged request body and rejects anything that doesn't match. | -| **Verify Token** | You | Answers Meta's one-time verification challenge when you save the callback URL. It does nothing after that. | -| **Webhook URL** | Artemis | Receives events. The route carries no account ID, because the account ID travels in the payload. | +| Piece | Owner | What it does | +|---|---|---| +| **Instagram Account ID** | Meta | Routes inbound events by matching `entry.id`. | +| **Page Access Token** | Meta | Authorizes replies. Artemis sends them to `/{InstagramAccountId}/messages` with the token as a Bearer token. | +| **App Secret** | Meta | Verifies `X-Hub-Signature-256` on every inbound POST, over the exact raw body. | +| **Verify Token** | You | Answers Meta's one-time verification challenge. | +| **Webhook URL** | Artemis | Receives events at `/api/v1/channels/instagram/webhook`, with no identifier suffix. | -Artemis scopes each conversation to the account and the sender together, so one person messaging two of your professional accounts holds two separate sessions. +Artemis scopes each conversation to the account and the sender together, as an `instagram:{accountId}:{senderId}` session. --- ## Instagram and Meta setup -Do this work in Instagram and Meta before you open Artemis. Meta covers the same ground in its [Instagram messaging get started guide](https://developers.facebook.com/docs/messenger-platform/instagram/get-started). +Do this in Instagram and Meta before you open Artemis. Select **Open Meta for Developers** in the setup guide to jump straight there. Meta covers the same ground in its [Instagram messaging get started guide](https://developers.facebook.com/docs/messenger-platform/instagram/get-started). - - 1. Open the Instagram app and go to your profile. - 2. Open the menu, then **Settings and privacy**. - 3. Find the account type setting and switch the account to **Business** or **Creator**. - - Instagram messaging works only on a professional account, and the [Instagram Platform overview](https://developers.facebook.com/docs/instagram-platform/overview/) sets out what each account type supports. A personal account can't support this integration at all, so confirm this before you spend time in the App Dashboard. + + 1. In the Instagram app, open your profile, then the menu, then **Settings and privacy**. + 2. Switch the account type to **Business** or **Creator**. - 1. In Instagram, open the professional account settings and find the linked accounts or connected Page setting. - 2. Connect the Facebook Page that will issue the Page Access Token. - 3. Confirm the link from the Page side as well, so both surfaces agree. - - The Page is what makes messaging work. Meta routes Instagram conversations through the linked Page, which is why the token you use later belongs to the Page rather than to Instagram. + 1. In the professional account settings, connect the Facebook Page that will issue the Page Access Token. + 2. Confirm the link from the Page side too. - 1. Sign in to [Meta for Developers](https://developers.facebook.com/) and open [My Apps](https://developers.facebook.com/apps/). - 2. Create an app, choosing the business messaging use case, or open the app that will own this connection. - 3. Add the Instagram product and configure Instagram messaging for the linked Page and account. + 1. Open [My Apps](https://developers.facebook.com/apps/) and create an app with the business messaging use case, or open an existing one. + 2. Add the Instagram product and configure Instagram messaging for the linked Page and account. - Keep development and production on separate apps and accounts, because app mode and webhook subscriptions belong to the app. + Keep development and production on separate apps and accounts. - 1. Grant the app, its testers, and any system users the Instagram messaging and Page permissions they need. - 2. Complete any permission review Meta requires for your current app mode. - 3. Generate a Page Access Token for the linked Page and copy it. - - Meta requires the `instagram_manage_messages` permission on the token, and requires that whoever requests it can perform the messaging and moderate tasks on the Page. A token generated without both produces a clean-looking connection that fails on the first reply. + 1. Grant the app, testers, and system users the Instagram messaging and Page permissions they need. + 2. Complete any permission review your app mode requires. + 3. Generate a Page Access Token for the linked Page. - Token lifetime follows the user token behind it. A short-lived user token yields a Page token good for about an hour. A long-lived user token yields one with no expiry, so use the long-lived path for anything beyond a first test. + The token needs `instagram_manage_messages`. A token from a short-lived user token lasts about an hour, and one from a long-lived user token doesn't expire. - Artemis routes on the numeric professional account ID, which is neither the `@username` nor the Page ID. - - Meta surfaces it in the Instagram messaging setup area of the App Dashboard alongside the connected account. You can also query the linked Page for its connected Instagram professional account in the Graph API Explorer, which returns the same numeric ID. + Copy the numeric professional account ID from the Instagram messaging area of the App Dashboard. You can also query the linked Page for its connected Instagram account in the Graph API Explorer. - Don't substitute the `@username`, the Facebook Page ID, the Meta App ID, a profile URL, or the Instagram-scoped ID. That last one, the IGSID, appears in every inbound event and identifies the customer: Meta issues each person a different scoped ID for each account they message. + Don't use the `@username`, the Facebook Page ID, the Meta App ID, a recipient PSID, or a profile URL. - 1. In the left menu of the App Dashboard, go to **App settings** -> **Basic**. - 2. Click **Show** beside **App secret**. - 3. Re-enter your Facebook password when Meta asks, then copy the value. + 1. Go to **App settings** -> **Basic**. + 2. Select **Show** beside **App secret**, re-enter your password, and copy the value. - Take it from the same Meta app that owns the Instagram webhook. An App Secret from a neighboring app produces a signature failure on every event, which is a confusing failure to trace because nothing else looks wrong. + Use the App Secret from the same app that owns the Instagram webhook. - Invent a long random string. Meta doesn't issue this one, so you create it and enter the same value twice: once in Artemis, once in the Meta webhook form. - - Use a different value per environment, and treat it as a secret rather than a label. It's your shared challenge secret, distinct from both the Page Access Token and the App Secret. - - - - While the app sits in development mode, only accounts holding an app role or an eligible Instagram tester role can exercise the integration. - - Before ordinary people can message the account, complete permission review and switch the app to Live using the control at the top of the App Dashboard. A successful test with a role-holding account proves nothing about public access. + Create a long random value that only Artemis and the Meta webhook form know. Use a different value per environment. @@ -119,76 +102,50 @@ Do this work in Instagram and Meta before you open Artemis. Meta covers the same ## Artemis channel configuration -Create the connection before you configure the callback in Meta. Meta's verification request carries the Verify Token but no account ID, so Artemis resolves the challenge from the stored token and needs the connection to exist and be active. +Create the connection before you select **Verify and Save** in Meta. Artemis resolves Meta's challenge from a hash of the saved Verify Token. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **Instagram** -> **+ New**. -3. Configure the following fields: - - | Artemis connection field | Source / Notes | - |---|---| - | Display Name | The label operators see in the connections list. Name it for the account and the environment it serves, because a project can hold several Instagram connections. Routing ignores this value. | - | Instagram Account ID | The routing key. Enter the numeric professional account ID. From the Instagram messaging area of the Meta App Dashboard, or from the linked Page in the Graph API Explorer. | - | Page Access Token | Authorizes outbound replies. Use the token generated for the Facebook Page linked to this Instagram account, carrying the Instagram messaging permission. | - | App Secret | Verifies the signature Meta puts on each inbound event. From **App settings** -> **Basic** in the same Meta app that owns the webhook. | - | Verify Token | The string you invented. Enter the identical value in Meta when you register the callback. | - | Environment | The published environment whose active deployment answers incoming messages. Leave the working copy default only while you develop. | - | Provider Verification Strength | How far Artemis trusts Meta's identity assertion when it links a person to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Whether the connection starts handling messages. Set it to **Active**, because Meta's verification challenge resolves only when the connection is already active. | - -4. Click **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab.
- Copy it exactly. The route carries no account identifier, and adding one breaks the callback rather than refining it. - -### Validation checklist - -| Validation item | Expected result | -|:---|:---| -| Convert the Instagram account | Account shows as Business or Creator and is eligible for Instagram messaging. | -| Link the Facebook Page | Instagram account and Page show as linked from both sides, with messaging and moderate tasks available to you. | -| Prepare the Meta app | Instagram product added, permissions assigned, and a non-expired Page Access Token generated for the linked Page. | -| Collect the routing identifier | Numeric Instagram Account ID copied, distinct from the `@username`, Page ID, and App ID. | -| Create the Artemis connection | Connection saved as Active with the account ID, Page Access Token, App Secret, and Verify Token. | -| Register the callback | Meta reports the webhook verified, with `messages` and `messaging_postbacks` subscribed and the intended account connected. | -| Bind a deployment | The connection's **Deployment** tab shows a runnable active deployment. | -| Send a real message | Test direct message reaches the agent and the reply returns once. See [Verify the connection](#verify-the-connection). | +2. Go to **Deployments** -> **Channels** -> **Instagram** -> **+ New**. The **New Instagram Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see. Name it for the account and environment. Routing ignores it. | + | **Instagram Account ID** | The App Dashboard or Graph API Explorer | The routing key, matched to `entry.id` in each webhook. | + | **Page Access Token** | The linked Facebook Page | Authorizes replies to `/{InstagramAccountId}/messages`. | + | **App Secret** | **App settings** -> **Basic** | Validates `X-Hub-Signature-256` over the exact raw POST body. | + | **Verify Token** | You create it | Your shared challenge secret. It isn't the Page Access Token or the App Secret. | + | **Environment** | Your published environments | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Meta's identity assertion when it links a person to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | Keep it **Active**. Meta's challenge resolves only for an active connection. | + +4. Select **Create**. +5. Copy the **Webhook URL** from the connection's summary panel. Don't add an account ID or any suffix. --- ## Webhook configuration in Meta -Registration has two halves, and completing only the first is the most common way a setup fails silently. Meta verifies the URL whether or not you subscribe to anything. - - - - 1. In the same Meta app, open the Instagram webhook configuration. - 2. Paste the Artemis **Webhook URL** exactly as shown. - 3. Enter the same **Verify Token** you saved in Artemis. - 4. Click the control that verifies and saves the callback. - - Meta sends a subscribe challenge and expects your Verify Token echoed back. Artemis returns the challenge only when the token matches an active Instagram connection. A failure here points at the token, the connection status, or public reachability over HTTPS rather than at the URL itself. - - Don't append an account ID, a connection ID, a query string, or a trailing segment. - - - - Subscribe the Instagram webhook to `messages` and `messaging_postbacks`, then save the subscription. +Registration has two halves. Meta verifies the URL whether or not you subscribe to anything, so finish both. - The `messages` field carries text, attachments, and quick-reply payloads, so it's required even for an agent that only handles text. `messaging_postbacks` carries the action callbacks behind buttons and template elements. - - - - Confirm the app connects to the same Instagram account, and that the Page subscription includes it. +1. Confirm the Artemis connection exists and is **Active**. +2. In the same Meta app, open the Instagram webhook configuration and paste the Artemis **Webhook URL** exactly. +3. Enter the same **Verify Token** and select **Verify and Save**. Meta sends `hub.mode=subscribe`, `hub.verify_token`, and `hub.challenge`, and Artemis returns the challenge only when the token matches an active Instagram connection. +4. Subscribe to `messages` for text, attachments, and quick replies, and `messaging_postbacks` for action callbacks. Save the subscription. +5. Confirm the app and the Page subscription connect the same Instagram account. Artemis rejects a connection mismatch. +6. Make sure any proxy in front of Artemis keeps `X-Hub-Signature-256` and passes the raw body unchanged. - Artemis resolves each event by the account ID in the signed payload, so an app subscribed to a different account delivers events that no connection claims. - +### Validation checklist - - Meta signs every POST with `X-Hub-Signature-256`, and Artemis computes the HMAC over the exact raw bytes. +Work down this list once per connection. - Any proxy or middleware in front of Artemis has to pass the body through untouched and keep the header. Parsing and reserializing the JSON changes the digest even when the content stays identical, which produces a signature failure that looks like a credential problem. - - +| Validation item | Expected result | +|:---|:---| +| Prepare the account | Business or Creator account, linked to a Page where you hold messaging and moderate tasks. | +| Prepare the app | Instagram product added, permissions granted, and a valid Page Access Token. | +| Create the Artemis connection | Saved as **Active** with the account ID, token, App Secret, and Verify Token. | +| Register the webhook | Meta verifies the callback, with `messages` and `messaging_postbacks` subscribed for the intended account. | +| Send a real message | A direct message reaches the agent and one reply returns. | --- @@ -196,101 +153,98 @@ Registration has two halves, and completing only the first is the most common wa Artemis doesn't synthesize Meta events, so a real Instagram conversation is the only end-to-end proof. -1. From an account holding an app or Instagram tester role, send the professional account a short direct message you can search for later. -2. Confirm Meta reports a successful delivery and that Artemis opens one session.
- Artemis ignores echo events, so your own outbound messages shouldn't create extra turns. -3. Check that a single reply reaches the original sender in the same conversation.
- A send failure here usually means the Page Access Token is wrong or expired, the account linkage broke, the messaging permission is missing, or the conversation has fallen outside the messaging window. -4. Trigger an authored quick reply and a template action, and confirm each resumes the same session rather than starting a new one. -5. Send an image, video, audio file, and document, and confirm the agent handles the downloaded attachment.
- Artemis downloads signed Meta CDN URLs promptly because they expire, so a delay in your own processing isn't the same as a delivery failure. -6. Once Meta approves the app and you switch it to Live, repeat the test from an account with no role. This is the only check that proves ordinary people can reach the agent. +1. While the app is in Development, send from an account with an app or Instagram tester role. A public user proves nothing until review and Live mode are complete. +2. Send a unique text to the professional account. Confirm one signed `messages` event, one session, and no processing of echo events. +3. Confirm the reply reaches the original sender through `/{InstagramAccountId}/messages`, inside the messaging window. +4. Select an authored quick reply and a generic-template action. Confirm each resumes the same `instagram:{accountId}:{senderId}` session. +5. Send image, video, audio, and file attachments. Artemis downloads signed Meta CDN URLs promptly, before they expire, and applies size and attachment policy. + +| Input | What to confirm | +|---|---| +| `text` | The agent receives and answers it. | +| `image`, `video`, `audio`, `file` | The download succeeds and the agent processes the file. | +| `quick replies`, `postbacks` | The selection returns to the same session with the right action. | --- -## Instagram channel behavior and limits +## Instagram behavior and limits -Meta enforces these boundaries, and Artemis applies its own download policy on inbound media. Design your agent's responses to fit them. +Design agent responses to fit these limits. | Area | Limit | -| ---- | ----- | -| Quick replies | Buttons and selects become quick replies, capped at 13 options with visible titles truncated to 20 characters. | -| Carousels | Generic-template rich content supports at most 10 elements, each carrying at most 3 buttons. | -| Unsupported inputs | Artemis ignores share, story mention, like-heart, reel, sticker, and fallback-only attachments rather than turning them into blank agent turns. | -| Media downloads | Image, video, audio, and file downloads accept only recognized Meta and Instagram CDN hosts, time out after 30 seconds, and cap at 100 MB streaming. | -| Messaging window | Meta can reject outbound delivery outside the Instagram messaging window, which runs 24 hours from the person's message. A human agent tag extends that to 7 days for approved use cases. | -| Rate limits | Meta allows roughly 100 calls per second per account for text messages, and roughly 10 per second for audio or video. | +|---|---| +| Quick replies | Buttons and selects become quick replies, up to 13 options, with titles truncated to 20 characters. | +| Carousels | Generic templates support up to 10 elements, each with up to 3 buttons. | +| Ignored inputs | Artemis ignores shares, story mentions, like-hearts, reels, stickers, and fallback-only attachments rather than creating blank agent turns. | +| Media downloads | Recognized Meta and Instagram CDN hosts only, a 30-second timeout, and a 100 MB streaming cap. | +| Messaging window | Meta can reject replies outside the Instagram messaging window. Test expected conversation timing and approved use cases before production. | --- -## Secure the connection +## Security and lifecycle -Instagram authentication runs in one direction only, which is easy to misread. Meta signs what it sends you; your Verify Token does nothing after setup. +Meta signs what it sends. Your Verify Token only protects the one-time challenge. -Every POST requires `X-Hub-Signature-256` generated with the matching App Secret, and Artemis rejects a missing or invalid signature before it queues anything. Signature validation covers the exact raw bytes, so preserve the request body, its content encoding, the header, and the external scheme through your ingress. - -Keep the three secrets distinct in your own operational notes. The Verify Token protects only the one-time challenge, and you rotate it in both Artemis and Meta together. The App Secret authenticates inbound traffic. The Page Access Token authorizes outbound messages, so encrypt it, redact it from logs, grant least privilege, monitor its expiry, and never expose it to browser code. - -Use separate Meta apps and accounts for development and production, or at minimum isolated credentials, tokens, webhook subscriptions, and connections. +- **Signatures**: Artemis rejects any POST without a valid `X-Hub-Signature-256` before queueing. Preserve the request body, content encoding, header, external scheme, and proxy behavior through ingress. +- **Verify Token**: Use a unique random value per environment, and rotate it in Artemis and Meta together. +- **Page Access Token**: It authorizes outbound messages. Encrypt and redact it, grant least privilege, monitor expiry, rotate it, and keep it out of browser code. +- **Environments**: Use separate Meta apps and accounts, or at least isolated credentials, tokens, subscriptions, and connections, for development and production. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **Instagram** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to register in Meta and the **Instagram Account ID** this connection matches events to, each with a copy control. Check the account ID here first when messages arrive and no session appears. - +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Instagram** and **Channel Connection**. | +| **Identifier** | The Instagram Account ID this connection routes on. Check it first when messages arrive and no session appears. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The callback URL for Meta, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + - Artemis encrypts credentials after you save them, so each field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new one to replace it. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credentials from a saved auth profile instead of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | **Page Access Token** | Replace it here when you generate a new token in Meta. The account ID stays the same, so you don't need a new connection. | - | **App Secret** | Replace it here if you move the Instagram product to a different Meta app. | - | **Verify Token** | Changing this breaks Meta's webhook until you enter the matching value in Meta as well. | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **Page Access Token** | Replace it when you generate a new token in Meta. | + | **App Secret** | Replace it if the Instagram product moves to another Meta app. | + | **Verify Token** | Changing it breaks the Meta webhook until you enter the same value in Meta. | - Click **Save Credentials** to apply your changes. + Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this account changes. - - Under **Instagram Settings**, **Instagram Account ID** appears read-only. Artemis routes inbound events by this value, so changing it would orphan the connection. Create a new connection to serve a different account. + Update how the connection behaves. **Instagram Settings** holds the provider-specific fields. - **Authorization Message** controls what the person sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. - - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | - - Item variables resolve only inside the repeat block. Use the preview to check the wording, and remember it fills from live pending authorizations at runtime. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Meta's identity assertion. | + | **Instagram Account ID** | Read-only, with a copy control. To serve another account, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The callback URL, with a copy control. | - Click **Save Changes** to apply your changes. + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers Instagram messages. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic and when someone deployed it. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Check this pair when the channel connects but the agent behaves like an older build. The connection follows whatever the environment currently has deployed, not the version you last edited. Click **Save Changes** after you switch the environment. + Select **Save Changes** after you switch the environment. @@ -298,34 +252,34 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Most failures trace to the token, the App Secret, or the subscription. + | Symptom | Likely cause | Recommended action | |---|---|---| -| Meta can't verify the callback | The connection doesn't exist yet, the tokens differ, or the endpoint isn't publicly reachable | Create the connection and set it to Active first, use the exact saved Verify Token in both systems, expose the runtime over public HTTPS, and keep the generic Instagram webhook path. | -| Inbound requests return 401 | The App Secret belongs to a different app, or ingress altered the signed request | Confirm the App Secret comes from the app that owns the webhook, preserve `X-Hub-Signature-256`, and stop proxies from parsing and reserializing the JSON body. | -| Artemis reports no connection found | The account ID in the payload doesn't match the saved value | Compare the account ID in the signed payload with the **Instagram Account ID** saved in Artemis, and confirm the connection is Active. A Page ID or an IGSID in this field produces exactly this result. | -| Verification succeeded but no messages arrive | The subscription is missing, or the sender isn't eligible in the current app mode | Subscribe `messages` and `messaging_postbacks`, connect the intended professional account, inspect Meta's delivery log, and confirm the sender holds a role while the app is in Development. | -| Inbound works but outbound fails | The Page Access Token is wrong, expired, or under-permissioned, or the window closed | Verify the token, the account linkage, the Instagram messaging permission, the token expiry, the messaging window, and reachability of the Graph API. | -| Text works but actions don't | `messaging_postbacks` isn't subscribed, or the payload exceeds channel limits | Subscribe the field, then keep authored quick replies and template payloads within the limits above. | -| Text works but attachments fail | The media type, host, size, or signed URL falls outside policy | Use image, video, audio, or file, confirm the signed URL hasn't expired, confirm the host is a recognized Meta CDN, keep the download within 100 MB, and confirm your attachment policy accepts it. | -| Meta rejects replies after a delay | The conversation fell outside the messaging window | Reproduce inside an active conversation, then review Meta's current Instagram messaging window and approved use cases. | +| Meta can't verify the callback | No active connection, mismatched token, or unreachable endpoint | Create the **Active** connection first, use the same Verify Token in both systems, expose public HTTPS, and keep the generic Instagram webhook path. | +| Inbound requests return `401` | Wrong App Secret or altered request | Use the App Secret from the app that owns the webhook, preserve `X-Hub-Signature-256`, and stop proxies from reserializing JSON. | +| No connection found | The payload's account ID doesn't match | Compare `entry.id` with the saved **Instagram Account ID**. A Page ID or sender ID in that field produces this result. | +| Verified but no messages arrive | Missing subscription or ineligible sender | Subscribe `messages` and `messaging_postbacks`, connect the intended account, inspect Meta deliveries, and confirm the sender holds a role in the current app mode. | +| Inbound works but outbound fails | Token, linkage, or window issue | Check the Page Access Token, account linkage, permissions, token expiry, messaging window, and Graph API reachability. | +| Text works but actions don't | Missing postbacks subscription or oversized payload | Subscribe `messaging_postbacks`, and keep quick-reply and template payloads within the limits. | +| Text works but attachments fail | Media outside policy | Use image, video, audio, or file, confirm the signed URL hasn't expired, the host is a recognized Meta CDN, the download is within 100 MB, and your attachment policy accepts it. | +| Meta rejects replies after a delay | The messaging window closed | Reproduce inside an active conversation, and review Meta's current messaging window and approved use cases. | --- ## Meta reference -Use these Meta pages when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. | Resource | Use it for | -| -------- | ---------- | -| [Instagram Platform overview](https://developers.facebook.com/docs/instagram-platform/overview/) | Account eligibility, how the pieces fit together, and rate limits. | -| [Instagram messaging get started](https://developers.facebook.com/docs/messenger-platform/instagram/get-started) | Meta's own walkthrough of app setup, permissions, and Page token generation. | -| [Instagram messaging overview](https://developers.facebook.com/docs/instagram-messaging/overview) | Conversation entry points, supported message types, and the inbox model. | -| [Send a message](https://developers.facebook.com/docs/messenger-platform/instagram/features/send-message) | Outbound message formats, media limits, and the messaging window rules. | -| [My Apps](https://developers.facebook.com/apps/) | Returning to an app you created, or checking which app owns a subscription. | -| [Meta Business Suite](https://business.facebook.com/) | Page roles, linked accounts, and business verification. | +|---|---| +| [Instagram Platform overview](https://developers.facebook.com/docs/instagram-platform/overview/) | Account eligibility and rate limits. | +| [Instagram messaging get started](https://developers.facebook.com/docs/messenger-platform/instagram/get-started) | App setup, permissions, and Page tokens. | +| [Send a message](https://developers.facebook.com/docs/messenger-platform/instagram/features/send-message) | Outbound formats and messaging window rules. | +| [My Apps](https://developers.facebook.com/apps/) | Returning to an app or checking which app owns a subscription. | {{related}} +- [Channels](/agent-platform/channels) - [Set up Messenger](/agent-platform/channels/messenger) -- [Set up WhatsApp](/agent-platform/channels/whatsapp) -- [Set up LINE](/agent-platform/channels/line) \ No newline at end of file +- [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file diff --git a/agent-platform/channels/kore-agent-assist.mdx b/agent-platform/channels/kore-agent-assist.mdx index 28c8867af..a780a82be 100644 --- a/agent-platform/channels/kore-agent-assist.mdx +++ b/agent-platform/channels/kore-agent-assist.mdx @@ -1,103 +1,94 @@ --- -title: "Kore Agent Assist" -sidebarTitle: "Kore Agent Assist" +title: Set up Kore Agent Assist +sidebarTitle: Kore Agent Assist --- -The Kore Agent Assist channel connects an Artemis project to Kore Agent AI, so your deployed agents give contact center agents real-time guidance. Artemis creates the connection, generates its API key, binds it to an environment, and controls traffic through **Pause** and **Resume**. Kore Agent AI keeps calling the existing Agent Assist API, so the external endpoint contract doesn't change. +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) + +Connect an Artemis project to Kore Agent AI so your deployed agent gives contact center agents real-time guidance. Artemis owns the connection, its generated API key, the environment binding, and the pause state. Kore Agent AI keeps calling the existing Agent Assist API, so the external endpoint contract doesn't change. The setup requires: -1. [Create the connection in Artemis](#create-the-connection-in-artemis) -2. [Configure Kore Agent AI](#configure-kore-agent-ai) -3. [Verify the connection](#verify-the-connection) +1. [Create the connection in Artemis](#create-the-connection-in-artemis) and copy its four values. +2. [Configure Kore Agent AI](#configure-kore-agent-ai) with those values. +3. [Verify the connection](#verify-the-connection) from the **Testing** tab. -After setup, Kore Agent AI routes each Agent Assist session to the agent version active in the environment you select. +After setup, Kore Agent AI routes each Agent Assist session to the agent version active in the bound environment. **Important considerations** -- **The API key appears only once.** Artemis shows the full key only in the creation dialog. Afterward, only the key prefix stays visible. Copy the key before you select **Done**. -- **Pause and Resume control traffic.** The connection has no separate on or off setting. A paused or inactive connection returns `404` to external requests. -- **Use one connection per environment.** Keep development, staging, and production on separate connections, each with its own key. -- **The key has a narrow scope.** It covers message sending for the owning project only and doesn't grant platform administration access. -- **Output supports text and markdown.** Responses can also carry normalized renderables, actions, and activity events. The channel doesn't accept attachments or deliver channel-native rich media. +- **The API key appears only once**: Artemis reveals the full key at creation. Afterward, only its prefix stays visible. If you lose it, rotate it. +- **Pause and Resume control traffic**: There's no separate enable toggle. A paused or inactive connection returns not found to every external request. +- **Use one connection per environment**: Keep development, staging, and production on separate connections, each with its own key. +- **The key has a narrow scope**: It grants `session:send_message` for the owning project only, not platform administration. ## Prerequisites -Confirm the following before you start. +Confirm these before you start. -- An Artemis project with an agent version deployed to the target environment. The connection's **Deployment** tab lists it as the **Active Deployment**. -- Access to **Deployments** in the Artemis project. -- Administrator access to Kore Agent AI, including the **Configuration** section. -- A secure location, such as a secrets manager, to store the API key. +- An agent version deployed to the target environment. Kore Agent Assist requires a published environment. +- Artemis project access with permission to open **Deployments** -> **Channels**. +- Administrator access to Kore Agent AI, including **Configuration**. +- A secrets manager to store the API key. --- ## Create the connection in Artemis -Create the connection first. Artemis generates the four values that Kore Agent AI needs. - - - - 1. In your project, go to **Deployments** -> **Channels**. - 2. Select **Kore Agent Assist**. - 3. Select **Create Connection**. If the project already has connections, select **New**. - - - 1. In **Display Name**, enter a name that identifies the Agent Assist experience and its environment. The name supports up to 255 characters. - 2. In **Environment**, select the environment whose active deployment supplies the entry agent, welcome message, model, and runtime behavior. - 3. In **Initial Status**, select **Active** to accept traffic immediately, or select **Inactive** to save the connection and activate it later. - 4. Select **Create**. - - - The **Kore Agent Assist Connection Created** dialog shows four values. +Create the connection first. Artemis generates the four values Kore Agent AI needs. - 1. Copy **Domain URL**, **Environment**, **App ID**, and **API Key**. - 2. Store the API key in your secrets manager. - 3. Select **Done**. +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Kore Agent Assist** -> **+ New**. The **New Kore Agent Assist Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: - - After you close the dialog, Artemis can't show the full API key again. If you lose the key, rotate it from the **Overview** tab. - - - + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see. Name it for the Agent Assist experience and its environment. | + | **Environment** | The environment whose active deployment supplies the entry agent, welcome message, model, and runtime behavior. Kore Agent Assist requires a non-empty environment. | + | **Initial Status** | **Active** lets the API resolve the App ID and environment immediately. **Inactive** returns not found to external traffic until you activate it. | -### Connection values +4. Select **Create**. +5. Copy all four values that Artemis reveals, and store the API key in your secrets manager. -Each value maps to a field of the same name in Kore Agent AI. Copy each one exactly, including case and punctuation. +| Value | What it is | Watch for | +|---|---|---| +| **Domain URL** | The Artemis host that Kore Agent AI calls | Agent AI appends the API route itself. Don't paste an endpoint path. | +| **Environment** | The environment identifier | It can differ from the environment's display label. Copy the revealed value. | +| **App ID** | The project ID for the connection | Don't substitute the display name, an agent name, or a connection record ID. | +| **API Key** | A generated secret with the `abl_` prefix | Copy the full key now. Artemis can't show it again. | -| Value | Source / Notes | -|---|---| -| **Domain URL** | The Artemis host that Kore Agent AI calls. Agent AI appends the Agent Assist API route, so don't paste an individual endpoint path. | -| **Environment** | The environment identifier. It can differ from the label in the **Environment** list, so use the value from the dialog. | -| **App ID** | The project ID for the connection. Don't substitute the display name, an agent name, or the **Source ID** from the **Overview** tab. | -| **API Key** | A generated secret with the `abl_` prefix. Agent AI sends it in the `x-api-key` header. Keep it out of browser code, transcripts, client logs, and source control. | +The API key is reveal-once. If you lose it or suspect exposure, rotate it from the **Configuration** tab and update Kore Agent AI immediately. --- ## Configure Kore Agent AI -Add the connection as an Agentic Copilot app in Kore Agent AI. For the complete Agent AI procedure, see [Linked Services](https://docs.kore.ai/agentassist/settings/linked-services/). +Add the connection as an Agentic Copilot app in Kore Agent AI. Use the configuration for the same tenant, project, and environment as the Artemis connection. 1. Sign in to [Kore Agent AI](https://agentassist.kore.ai/koreagentassist/). - 2. Go to **Configuration** -> **System Setup** -> **Linked Services**. - 3. Select **Agentic Configurations**. - 4. Select **+ Add Agentic Copilot App**. + 2. Go to **Configuration** -> **System Setup** -> **Linked Services** -> **Agentic Configurations**. + 3. Select **+ Add Agentic Copilot App**. - - Under **App Information**, enter the values from the Artemis connection. - - 1. In **App Name**, enter a name that agents and administrators recognize. The name supports up to 50 characters. - 2. In **Domain URL**, paste the Artemis **Domain URL**. - 3. In **Environment**, paste the Artemis **Environment** value. - 4. In **App ID**, paste the Artemis **App ID**. - 5. In **API Key**, paste the full API key, not the prefix. + + + Under **App Information**, enter an **App Name**, then paste each value exactly, preserving case and punctuation. + + | Agent AI field | Artemis value | + |---|---| + | **Domain URL** | **Domain URL** | + | **Environment** | **Environment** | + | **App ID** | **App ID** | + | **API Key** | The full `abl_` key, not the prefix | + + Agent AI stores the key in its backend and sends it as `x-api-key`. Never expose it in browser code, transcripts, client logs, or source control. + - Select **Test Connection & Save**. Agent AI checks the values and saves the app when the connection succeeds. + Select **Test Connection & Save**. Agent AI builds the base path and sends `application/json` with `x-api-key` on every session, execute, terminate, and test request. - Next, link the app to your Agent AI experience so agents receive guidance at runtime. For details, see [Agentic Copilot](https://docs.kore.ai/agentassist/uncategorized/agentic-copilot/). + Then link the app to your Agent AI experience. See [Agentic Copilot](https://docs.kore.ai/agentassist/uncategorized/agentic-copilot/). @@ -105,165 +96,140 @@ Add the connection as an Agentic Copilot app in Kore Agent AI. For the complete Review these items before you route live conversations to the connection. -- The Artemis connection shows **Active** status. -- The selected environment has an **Active Deployment**. -- Agent AI holds the exact **Domain URL**, **Environment**, and **App ID** values. -- Agent AI holds the current, full API key. -- **Test Connection & Save** succeeds in Agent AI. -- Every action on the Artemis **Testing** tab returns a successful result. +| Validation item | Expected result | +|:---|:---| +| Artemis connection | Status shows **Active**, and the **Deployment** tab shows an **Active Deployment**. | +| Agent AI values | Domain URL, Environment, App ID, and the full current key match Artemis exactly. | +| Agent AI save | **Test Connection & Save** succeeds. | +| Artemis **Testing** tab | Every test action returns a successful result. | --- ## Verify the connection -The **Testing** tab calls the live Agent Assist API with the connection's saved values. Run it before you add the values to Agent AI, and again after any key rotation. - - - - 1. Open the connection, and select the **Testing** tab. - 2. Under **Connection**, confirm the **Domain URL**, **Environment**, and **App ID**. - 3. In **API Key**, paste the full key you stored at creation. The test actions stay unavailable until you paste a key. - - - Artemis generates a **sessionReference** for the test session. Run the actions in order so every call uses the same session. - - 1. Select **Test connection** to check authentication and deployment readiness. - 2. Select **Connect (welcome)** to open the session and receive the agent's welcome message. - 3. In **Message**, enter a test message, and select **Send message**. - 4. Turn on **Stream response (SSE)**, and send another message to check streaming delivery. - 5. Select **Terminate** to end the session. - - - **Results** lists the request, status, duration, and response for each action. To start over with a new session reference, select **New session**. - - - -### Test actions +The **Testing** tab calls the live Agent Assist API with the connection's saved values. Run it before you configure Agent AI, and again after any key rotation. -Each test action calls one Agent Assist API endpoint. +1. Open the connection and select the **Testing** tab. +2. Under **Connection**, confirm the **Domain URL**, **Environment**, and **App ID**. +3. In **API Key**, paste the full key you stored. The test actions stay unavailable until you do. +4. Run the actions in order. They all share the generated **sessionReference**. +5. Review **Results**, which lists each request, status, duration, and response. Select **New session** to start over with a new reference. | Action | Endpoint | What it confirms | |---|---|---| -| **Test connection** | `/test` | The key authenticates, the App ID and environment resolve, and the deployment, entry agent, and model are ready. The call doesn't create a conversation or call the model. | -| **Connect (welcome)** | `/sessions` | The API creates the session and returns the authored welcome message. | -| **Send message** | `/runs/execute` | The agent processes a turn and returns a response. With **Stream response (SSE)** on, the response arrives as a Server-Sent Events stream. | -| **Terminate** | `/sessions/terminate` | The API ends the session and returns a termination response. | +| **Test connection** | `/test` | The key authenticates, the App ID and environment resolve, and the deployment, entry agent, and model are ready. No conversation, no model call. | +| **Connect (welcome)** | `/sessions` | The session opens and returns the authored welcome message. | +| **Send message** | `/runs/execute` | The agent answers a turn. Turn on **Stream response (SSE)** to check streaming delivery. | +| **Terminate** | `/sessions/terminate` | The session ends and returns a termination response. | ### Verify pause and resume Confirm that the connection status controls all external traffic. -1. In the connection header, select **Pause**. -2. On the **Testing** tab, select **Test connection**, and confirm the request returns `404`. +1. Select **Pause** in the connection header. +2. Run **Test connection**, and confirm it returns not found. 3. Select **Resume**, and run **Test connection** again. --- -## Manage the connection - -Open a connection from **Deployments** -> **Channels** -> **Kore Agent Assist**. The header shows the display name, environment, and status, plus the **Pause** and delete controls. +## Manage the channel connection -| Tab | Use it to | -|---|---| -| **Overview** | Review the **Connection Summary**, copy the Agent AI values, and rotate the API key. | -| **Configuration** | Change the **Display Name**, and then select **Save Changes**. | -| **Deployment** | Change the environment that handles incoming messages, and review the **Active Deployment** version and deployment time. | -| **Testing** | Run test actions through the live API. | +Open a connection from **Deployments** -> **Channels** -> **Kore Agent Assist** to manage it. The page has a header, three tabs, and a summary panel on the right. -### Connection summary +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. **Pause** and **Resume** control external traffic, and the **...** overflow menu holds the other connection-level actions. Before you delete a connection, remove or update the matching app in Agent AI. -The **Overview** tab lists the connection's metadata under **Connection Summary**. +**Summary panel.** Stays visible on every tab. | Field | Description | |---|---| -| **Status** | Whether the connection accepts external traffic. | -| **Created** | When you created the connection. | -| **Updated** | When the connection last changed. | -| **Environment** | The environment identifier the connection follows. | -| **Source Type** | The record type. For this channel, the value is **Channel Connection**. | -| **Source ID** | The internal ID of the connection record. Don't use it as the App ID. | - -### Change the environment +| **Channel** and **Connection Type** | Read **Kore Agent Assist** and **Channel Connection**. | +| **Identifier** | The App ID and environment this connection resolves, joined by a colon. | +| **Created** and **Updated** | Date and time of creation and of the last change. | -Changing the environment routes incoming messages to that environment's active deployment. + + + Under **Kore Agent AI configuration**, copy the values Agent AI needs and rotate the key. -1. Select the **Deployment** tab. -2. In **Environment**, select the environment. -3. Select **Save Changes**. -4. On the **Overview** tab, check the **Environment** value, and update Agent AI if it differs. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Domain URL**, **Environment**, **App ID** | Read-only, each with a copy control. | + | **API Key** | Masked. Select **Rotate** to replace it. | -### Rotate the API key + To rotate the key: -Rotate the key when you lose it or suspect exposure. + 1. Select **Rotate** beside **API Key**. + 2. Copy the new key. Artemis reveals it once and revokes the previous key as soon as it saves the replacement. + 3. In Agent AI, replace the **API Key** and select **Test Connection & Save**. -1. On the **Overview** tab, select **Rotate** next to **API Key**. -2. Copy the new key. Artemis shows it only once. -3. In Agent AI, replace the **API Key** value, and select **Test Connection & Save**. + Select **Save Changes** after you edit the **Display Name**. + - - Artemis revokes the previous key when it saves the replacement. Agent AI requests fail until you update the key. - + + Choose which deployed version answers Agent Assist sessions. -### Pause, resume, or delete + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | -Use the header controls to change the connection's availability. + Select **Save Changes** after you switch the environment. Then check the **Environment** value on the **Configuration** tab, and update Agent AI if it changed. + -- Select **Pause** to stop external traffic. Requests return `404` until you select **Resume**. -- Select the delete icon to remove the connection. Before you delete it, remove or update the matching app in Agent AI. + + Run the test actions through the live API. See [Verify the connection](#verify-the-connection). + + --- ## API reference -Kore Agent AI calls these endpoints on your behalf. Use this section to build a custom integration or to diagnose failed requests. +Kore Agent AI calls these endpoints for you. Use this section to build a custom integration or diagnose failed requests. ### Base path and authentication -All endpoints share one base path built from the connection values. +Every endpoint shares one base path built from the connection values. ```text {Domain URL}/api/v2/apps/{App ID}/environments/{Environment} ``` -Every request sends `Content-Type: application/json` and the full API key in the `x-api-key` header. Don't send an `Authorization: Bearer` header, a user token, an SDK public key, or the key prefix. The API checks that the key's tenant and project match the resolved App ID and environment, and returns `404` on any mismatch. +Send `Content-Type: application/json` and the full key in `x-api-key`. Don't send `Authorization: Bearer`, an Artemis user token, an SDK public key, or the key prefix. The API checks that the key's tenant and project match the resolved App ID and environment, and returns not found on any mismatch. ### Session lifecycle -Each Agent Assist conversation uses the same session identity across all calls. +Each conversation reuses the same session identity across every call. | Step | Endpoint | Details | |---|---|---| | Start | `POST /sessions` | Send `sessionIdentity` before the first turn. Set `metadata.isSendWelcomeMessage` to `true` to receive the welcome message. | | Send turns | `POST /runs/execute` | Send `sessionIdentity` and `input[]`. Reuse the same `sessionReference` for later turns. | -| End | `POST /sessions/terminate` | Send the same session identity when the conversation ends. The API returns a termination response even if the session no longer exists. | -| Check readiness | `/test` | Checks authentication and deployment readiness without creating a conversation or calling the model. | +| End | `POST /sessions/terminate` | Send the same identity when the conversation ends. The API returns a termination response even if the session is already gone. | +| Check readiness | `POST /test` | Reports agents, entry agent, deployment, and model readiness without a conversation or model call. | ### Response modes -`/runs/execute` supports three response modes. The request fields decide which mode applies. +The request fields on `/runs/execute` decide the response mode. | Mode | How to request it | Behavior | |---|---|---| -| Synchronous (default) | Leave streaming off, and omit `callbackUrl`. | Returns one completed response on the same HTTP connection. | -| Streaming (SSE) | Set `stream.enable` to `true`, and accept `text/event-stream`. | Streams the response with heartbeats, then sends the final session and run details. Streaming takes precedence over `isAsync`. | -| Async push | Set `isAsync` to `true`, and include `callbackUrl`. | Validates the callback, returns `202` with a processing state, and later delivers the completed or error response to the callback. | - - - If you set `isAsync` to `true` without a `callbackUrl`, the API falls back to the synchronous response. - +| Synchronous (default) | Leave streaming off and omit `callbackUrl`. | Returns one completed response on the same HTTP connection. | +| Streaming (SSE) | Set `stream.enable` to `true` and accept `text/event-stream`. | Streams the response with heartbeats, then sends the final session and run details. Takes precedence over `isAsync`. | +| Async push | Set `isAsync` to `true` and include `callbackUrl`. | Validates the callback, returns `202` with a processing state, and later delivers the completed or error response. | -For async push, use an approved HTTPS destination, and avoid private and link-local addresses. When callback signing is on, verify the `X-ABL-Signature` header, which signs `timestamp.rawBody`. +If `isAsync` is `true` but `callbackUrl` is missing, the API falls back to the synchronous response. For async push, use an approved HTTPS destination outside private and link-local ranges. When callback signing is on, verify `X-ABL-Signature`, which signs `timestamp.rawBody`. ### Payload rules -The API normalizes and restricts request content before agent execution. +The API normalizes and restricts request content before the agent runs. | Element | Rule | |---|---| -| `sessionIdentity` | Accepts `sessionReference`, `sessionId`, `sessionIdentity`, and `userReference` entries. Include at least one stable `sessionReference`, `sessionId`, or `userReference`, and keep it unchanged across calls. | -| `input[]` | Requires at least one item and supports `text`, `object`, and `tool_input` types. Agent execution needs a `text` item. Each content value allows up to 16,000 characters. | -| `metadata.aa_uamsgs` | Carries Agent Assist conversation history. The API keeps up to 50 messages. | -| Other `metadata` | The API accepts custom keys but strips reserved transport, credential, tenant, project, session, and authorization keys. | +| `sessionIdentity` | Accepts `sessionReference`, `sessionId`, `sessionIdentity`, and `userReference` entries. Include at least one stable `sessionReference`, `sessionId`, or `userReference`, and keep it unchanged. | +| `input[]` | Needs at least one item of type `text`, `object`, or `tool_input`. Agent execution needs a `text` item. Each content value allows up to 16,000 characters. | +| `metadata.aa_uamsgs` | Carries Agent Assist history. The API keeps up to 50 messages. | +| Other `metadata` | Accepts custom keys. The API strips reserved transport, credential, tenant, project, session, and authorization keys. | | Output | Text and markdown, plus optional normalized renderables, actions, and activity events. No attachments or channel-native rich media. | --- @@ -274,18 +240,16 @@ Match the symptom to its likely cause, and apply the recommended action. | Symptom | Likely cause | Recommended action | |---|---|---| -| `401 Unauthorized` | The request carries a missing, partial, or revoked key. | Paste the full current `abl_` key, and confirm every request sends `x-api-key`. | -| `404` app not found | The App ID or Environment doesn't match, the key belongs to another project, or the connection is paused or inactive. | Copy the values again from the **Overview** tab, and confirm the connection shows **Active**. | -| **Test Connection & Save** fails in Agent AI | One or more pasted values differ from the Artemis connection. | Recopy all four values with the copy icons on the **Overview** tab. | -| `/test` reports a deployment resolution failure | The environment has no active deployment, or its entry agent or model configuration isn't valid. | Deploy an agent version to the environment, and check the entry agent and model settings. | -| Streaming returns JSON or stalls | The request doesn't set `stream.enable`, doesn't accept `text/event-stream`, or a proxy buffers the stream. | Set `stream.enable` to `true`, accept `text/event-stream`, turn off proxy buffering, and let heartbeats pass for the full request timeout. | -| Async returns an invalid callback error or never delivers | The callback URL isn't an approved HTTPS destination, or signature checks fail. | Use an approved HTTPS URL outside private and link-local ranges, and verify `X-ABL-Signature` when signing is on. | -| Welcome and follow-up turns land in different sessions | The session identity changes between calls. | Reuse the same `sessionReference`, and keep identity values and their order unchanged between `/sessions` and `/runs/execute`. | -| Test actions stay unavailable | The **Testing** tab has no API key. | Paste the full key, or rotate it from the **Overview** tab and paste the new one. | - -## Related topics - -Use these pages to continue channel and deployment setup. +| `401 Unauthorized` | Missing, partial, or revoked key | Paste the full current `abl_` key, and confirm every request sends `x-api-key`. | +| `404` app not found | Wrong App ID or Environment, a key from another project, or a paused or inactive connection | Recopy the values from the **Configuration** tab, and confirm the connection shows **Active**. | +| **Test Connection & Save** fails in Agent AI | A pasted value differs from Artemis | Recopy every value with the copy controls on the **Configuration** tab. | +| `/test` reports a deployment resolution failure | No active deployment, or an invalid entry agent or model | Publish or activate the environment, and check its entry agent and model configuration. | +| Streaming returns JSON or stalls | Streaming isn't requested, or a proxy buffers the response | Set `stream.enable` to `true`, accept `text/event-stream`, turn off proxy buffering, and let heartbeats pass for the full timeout. | +| Async returns an invalid callback error or never delivers | Unapproved callback URL or failed signature check | Use an approved HTTPS URL outside private and link-local ranges, and verify `X-ABL-Signature` when signing is on. | +| Welcome and follow-up turns land in different sessions | The session identity changes between calls | Reuse the same `sessionReference`, and keep identity values and their order unchanged between `/sessions` and `/runs/execute`. | +| Test actions stay unavailable | The **Testing** tab has no key | Paste the full key, or rotate it from the **Configuration** tab and paste the new one. | + +{{related}} - [Channels](/agent-platform/channels) - [Deployment](/agent-platform/deployment) diff --git a/agent-platform/channels/line.mdx b/agent-platform/channels/line.mdx index fff0694b7..aaa7b2b56 100644 --- a/agent-platform/channels/line.mdx +++ b/agent-platform/channels/line.mdx @@ -3,301 +3,246 @@ title: Set up LINE sidebarTitle: LINE --- -[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect a LINE Official Account to your agent so people reach it in LINE for chat and media messaging. You create the Official Account, enable the Messaging API on it, collect two credentials and one identifier, then register a webhook and verify it before any real traffic arrives. +Connect a LINE Official Account to your agent so people reach it in LINE for chat and media messaging. You prepare a Messaging API channel, identify the bot, enter its credentials in Artemis, then register and verify the webhook. The setup requires: -1. [LINE setup](#line-setup): Create the Official Account, enable the Messaging API, and collect the Channel Secret, Channel Access Token, and Destination ID. -2. [Artemis channel configuration](#artemis-channel-configuration) using those three values, then copy the generated webhook URL. -3. [Webhook configuration in LINE](#webhook-configuration-in-line): Register the webhook URL, verify it, and switch delivery on. +1. [Prepare the LINE Official Account](#prepare-the-line-official-account) and its Messaging API channel. +2. [Artemis channel configuration](#artemis-channel-configuration): collect the bot's credentials and create the connection. +3. [Webhook configuration in LINE](#webhook-configuration-in-line): register, verify, and turn on the webhook. +4. [Verify the connection](#verify-the-connection) with a real LINE conversation. -After the configuration is complete, LINE posts every event for the channel to Artemis, which resolves the connection from the payload and hands the message to the deployed agent. +After setup, LINE posts every event for the channel to Artemis. Artemis resolves the connection from the payload, and the agent replies in the same chat. **Important considerations** -- **Two consoles, two halves of the job**: LINE splits the work between LINE Official Account Manager and the LINE Developers Console. Sign in to both with the same account. The Developers Console asks first-time users to register a developer profile with a name and email, and an account that skips that step can't see the channel it just created. -- **Official Account Manager creates the channel, not the Developers Console**: LINE removed the ability to create Messaging API channels directly in the Developers Console in September 2024. Enabling the Messaging API on the Official Account creates the channel. -- **Provider selection is permanent**: You can't change or remove the provider afterwards. A person also receives a different user ID under each provider, so moving an account later would break every stored user reference. -- **The Destination ID is not shown in either console**: It comes from an API call. Three identifiers that are shown look plausible and none of them route. See [How Artemis routes LINE events](#how-artemis-routes-line-events). - -| Console | What you do there | -| ------- | ----------------- | -| [LINE Official Account Manager](https://manager.line.biz/) | Create the Official Account, enable the Messaging API, and turn off LINE's automatic replies. | -| [LINE Developers Console](https://developers.line.biz/console/) | Copy the Channel Secret and access token, set the webhook URL, and find the friend-add QR code. | +- **The Destination ID selects the connection**: LINE sends the bot's user ID in each webhook's `destination` field, and Artemis uses it to find the connection before it verifies the signature. It must be the `U`-prefixed bot `userId`, not the numeric Channel ID, the `@`-prefixed Basic ID, or your personal user ID. +- **Official Account Manager creates the channel**: Enabling the Messaging API on the Official Account creates the channel. LINE no longer creates Messaging API channels directly in the Developers Console. +- **Provider selection is permanent**: You can't change it later, and each user gets a different user ID under each provider. +- **LINE turns on automatic replies by default**: Greeting messages and auto-reply messages send a LINE-managed response alongside the agent's reply. LINE recommends turning them off for a first Messaging API bot. ## Prerequisites -- A LINE Business ID, registered with an existing personal LINE account or with an email address. See [LINE setup](#line-setup). -- The admin role on the Official Account and on the Messaging API channel. Several steps hide their controls from lower roles rather than reporting a permission error. -- The admin role on the provider you intend to use, if you plan to select an existing one. A provider only appears in the selection list when your account holds that role on it. +Confirm these before you start. + +- A LINE Business ID, and admin access to the Official Account and its Messaging API channel. Lower roles can't see several controls. +- Admin access to the provider you intend to use. A provider appears in the list only when you hold that role. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- ## How Artemis routes LINE events -LINE sends every event for a channel to one URL, so Artemis identifies the connection from the payload rather than the path. Each webhook body carries a `destination` field holding the bot's user ID, and Artemis resolves the connection from that value before it verifies the signature. +LINE sends every event to one generic URL, so Artemis identifies the connection from the signed body. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Destination ID** | LINE | Routes inbound events. It has to be the bot's user ID, which begins with `U`. | -| **Channel Secret** | LINE | Verifies the `X-Line-Signature` header. Artemis computes HMAC-SHA256 over the unchanged request body and compares the result. | -| **Channel Access Token** | LINE | Authorizes outbound calls: replies, push messages, bot info lookups, and the loading indicator. | -| **Webhook URL** | Artemis | Receives events. The route carries no Destination ID, because the destination travels in the signed body. | - -Three LINE identifiers look plausible in the Destination ID field and none of them route. The **Channel ID** on the Basic settings tab is numeric. The **Bot basic ID** on the Messaging API tab starts with `@`. **Your user ID**, also on the Basic settings tab, is your own personal LINE account, not the bot's. The correct value comes from an API call, covered in [LINE setup](#line-setup). +| Piece | Owner | What it does | +|---|---|---| +| **Destination ID** | LINE | Routes inbound events by matching the top-level `destination` field. | +| **Channel Secret** | LINE | The HMAC-SHA256 key that verifies `X-Line-Signature` over the unchanged body. | +| **Channel Access Token** | LINE | Authorizes replies, push messages, bot info lookups, and the loading indicator. | +| **Webhook URL** | Artemis | Receives events at `/api/v1/channels/line/webhook`, with no identifier in the path. | --- -## LINE setup +## Prepare the LINE Official Account -Complete all of this in LINE before you open Artemis. Start at the beginning even if someone has already created an Official Account, because enabling the Messaging API is what creates the channel you'll configure. +Do this in LINE before you open Artemis. Select **Open Official Account Manager** or **Open LINE Developers Console** in the setup guide to jump straight there. - - LINE accounts for business sit behind a Business ID, which you can register with an existing personal LINE account or with an email address. + + In [LINE Official Account Manager](https://manager.line.biz/), create the customer-facing account or select the one that should represent the agent. Complete its name, profile image, region, and administrator access. - 1. Go to [account.line.biz](https://account.line.biz/signup?redirectUri=https://entry.line.biz/form/entry/unverified) and register a Business ID, if your organization doesn't already have one. - 2. Use an account your team can keep. This identity carries the admin role for everything that follows. - - - - 1. Complete LINE's [Official Account entry form](https://entry.line.biz/form/entry/unverified) with your business details. Submitting it creates the account. - 2. Open [LINE Official Account Manager](https://manager.line.biz/) and confirm the new account appears in your list before you continue. + For a new organization, register a Business ID at [account.line.biz](https://account.line.biz/) and complete the [Official Account entry form](https://entry.line.biz/form/entry/unverified) first. - 1. In Official Account Manager, select the account. - 2. Go to **Settings** -> **Messaging API** and enable the Messaging API. This is what creates the channel that Artemis connects to. - - You can't do this anywhere else. LINE removed the ability to create Messaging API channels directly in the Developers Console in September 2024. Starting from the developer side finds nothing to create. + Go to **Settings** -> **Messaging API** and enable it. Choose the correct LINE Developers provider. You can't treat provider ownership as an environment toggle later. - - LINE asks you to pick a provider, which is the organization that owns the channel. Two constraints make this a decision rather than a formality. - - You can't change or remove the provider afterwards. A person also receives a different user ID under each provider, so moving an account later would break every stored user reference. An existing provider only appears in the list when your account holds the admin role on it. A provider that seems to be missing is usually a permissions problem, not an absent one. - - Pick the provider that owns your related channels, and avoid putting unrelated services under one provider for convenience. + + In the [LINE Developers Console](https://developers.line.biz/console/), select the provider and the Messaging API channel linked to the Official Account. The **Basic settings** and **Messaging API** tabs hold the credentials and webhook controls. - - A new channel arrives with greeting messages and auto-reply messages enabled, which means a person gets one LINE-managed response and one agent response to the same message. - - Reach the settings from either console: - - 1. In Official Account Manager, open **Settings** -> **Response settings**. - 2. Or in the Developers Console, open the channel's **Messaging API** tab, where **Greeting messages** and **Auto-reply messages** each carry an **Edit** link that opens Official Account Manager at the right place. - - LINE recommends disabling both for a first Messaging API bot, and explains why under [settings on LINE Official Account Manager](https://developers.line.biz/en/docs/messaging-api/building-bot/#line-manager-settings). Disable both when the agent should own every reply. Keeping a greeting message is reasonable if you author it deliberately, but leaving the defaults on reads to users as a broken bot rather than as a settings problem. + + In Official Account Manager, open **Settings** -> **Response settings**. Turn off **Greeting messages** and **Auto-reply messages** when the agent owns every reply, or author them deliberately so users don't get conflicting responses. + - - All three credential values live in the Developers Console, spread across two tabs of the same channel. - - 1. Sign in at [developers.line.biz/console](https://developers.line.biz/console/). - 2. Select your provider, then select the Messaging API channel. - 3. Open the **Basic settings** tab and copy **Channel secret**. You need the admin role on the channel to see it. - - Take care not to grab the **Channel ID** or **Your user ID** from the same screen. Both sit nearby, both look like credentials, and neither works. - +--- - - Open the **Messaging API** tab. LINE offers four token types, and this screen issues only one of them. +## Artemis channel configuration - | Token type | Validity | Limit per channel | - | ---------- | -------- | ----------------- | - | User-specified expiration (v2.1) | Up to 30 days | 30 | - | Stateless | 15 minutes | No limit | - | Short-lived | 30 days | 30 | - | Long-lived | Until you revoke it | 1 | +Collect the credentials, then create the connection before you select **Verify** in LINE. - The long-lived token is the one with an **Issue** control on this tab. The other three come from API calls rather than the console, so choosing them means building issuance into your own tooling. + + + On the channel's **Basic settings** tab, copy **Channel secret**. You need the admin role to see it. Artemis uses it as the HMAC-SHA256 key for `X-Line-Signature` verification. + - LINE recommends the v2.1 token, and that recommendation costs you a rotation schedule. Pick the long-lived token if you'd rather not build that, and accept that a single indefinite credential carries more risk. Whichever you choose, copy the value straight into your secret manager. + + On the **Messaging API** tab, issue a token that can call the Messaging API. - Reissuing a long-lived token normally kills the previous one immediately. LINE lets you extend the outgoing token's validity by up to 24 hours when you reissue, which gives you a window to update Artemis without dropping messages. Use it. + | Token type | Validity | How to issue it | + |---|---|---| + | User-specified expiration (v2.1) | Up to 30 days | API call. LINE recommends it, so schedule rotation before it expires. | + | Long-lived | Until you revoke it | **Issue** on the **Messaging API** tab. Reissuing it invalidates the previous token immediately. | + | Short-lived or stateless | 30 days or 15 minutes | API call. | - - The console never shows this value, so you call for it. - - 1. Use LINE's [Get bot info](https://developers.line.biz/en/reference/messaging-api/#get-bot-info) endpoint with the channel access token you just issued. + + Call [Get bot info](https://developers.line.biz/en/reference/messaging-api/#get-bot-info) with the channel access token, and copy the `userId` from the response. It begins with `U`. - ```bash - curl -v -X GET https://api.line.me/v2/bot/info \ - -H "Authorization: Bearer {channel access token}" - ``` + ```bash + curl -X GET https://api.line.me/v2/bot/info \ + -H "Authorization: Bearer " - 2. Copy the `userId` from the response. + # Copy userId, not basicId or the numeric Channel ID + { + "userId": "U0123456789abcdef0123456789abcdef", + "basicId": "@123example", + "displayName": "Support Bot" + } + ``` - The value begins with `U` and matches the `destination` field LINE puts in every webhook for this channel. Run this from a secure terminal rather than a shared one, since the command carries your token. + Run it from a secure terminal, since the command carries your token. - - While you're on the **Messaging API** tab, find the QR code or add-friend link. You'll need it to test, and it's easier to grab now than to come back for. + + 1. In Artemis, go to **Deployments** -> **Channels** -> **LINE** -> **+ New**. The **New LINE Connection** dialog opens, with the setup guide on the left and the fields on the right. + 2. Configure the fields below, then select **Create**. + + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see. Name it for the Official Account and environment. Routing ignores it. | + | **Destination ID** | The routing key. Enter the `U`-prefixed bot `userId`. | + | **Channel Access Token** | Authorizes every outbound call to LINE. | + | **Channel Secret** | Verifies the signature on each inbound event. | + | **Environment** | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | How far the runtime trusts LINE's identity assertion when it links a person to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Keep it **Active**. LINE verification resolves only for an active connection. | + + Copy the **Webhook URL** from the connection's summary panel. ---- - -## Artemis channel configuration - -Create the connection before you verify the webhook in LINE. LINE's verification request has to resolve to an active connection and authenticate with that connection's Channel Secret, so an unsaved connection fails verification. - -1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **LINE** -> **+ New**. The **New LINE Connection** dialog opens. -3. Configure the following fields: - - | Artemis connection field | Source / Notes | What it controls | - |---|---|---| - | Display Name | You choose it | The label operators see in the connections list. Name it for the Official Account and the environment it serves, because a project can hold several LINE connections. Routing ignores this value. | - | Destination ID | The `userId` from Get bot info. See [LINE setup](#line-setup). | The routing key. It begins with `U`. | - | Channel Access Token | Developers Console > channel > **Messaging API** tab | The credential for every outbound call Artemis makes to LINE. | - | Channel Secret | Developers Console > channel > **Basic settings** tab | The key Artemis uses to verify the signature on each inbound event. | - | Environment | Your published environments | The environment whose active deployment answers incoming messages. Leave the working copy default only while you develop. | - | Provider Verification Strength | Defaults to **Weak** | How far Artemis trusts LINE's identity assertion when it links a person to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Defaults to **Active** | Whether the connection starts handling messages. Set it to **Active**, because LINE's verification resolves only when the connection is already active. | - -4. Click **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab. You need it for the next section. +Treat both credentials as secrets. Never place the Channel Secret or Channel Access Token in browser code, screenshots, tickets, or source control, and update Artemis as soon as LINE reissues or revokes either one. --- ## Webhook configuration in LINE -LINE separates saving the URL from switching delivery on, so a verified webhook can still deliver nothing. Complete all three parts in the Developers Console, on the channel's **Messaging API** tab. +LINE separates saving the URL from turning delivery on, so a verified webhook can still deliver nothing. - - - 1. Find **Webhook settings**. - 2. Click **Edit** under **Webhook URL**. - 3. Paste the Artemis endpoint exactly as shown and click **Update**. +1. Confirm the connection exists with the correct Destination ID and Channel Secret, and is **Active**. LINE's verify request has no user message, but Artemis still resolves and authenticates the connection. +2. In the Developers Console, open the channel's **Messaging API** tab and find **Webhook settings**. +3. Select **Edit** under **Webhook URL**, paste the Artemis URL exactly, and select **Update**. LINE accepts one webhook endpoint per channel. +4. Select **Verify** and require **Success**. LINE sends an empty-event POST, and Artemis answers after it resolves the connection and verifies the signature. Stop if LINE reports a timeout, a non-200 response, a TLS error, or a signature failure. +5. Turn on **Use webhook**. Without it, LINE never delivers message events. +6. Turn on **Webhook redelivery** only when your operations policy needs retries after non-2xx responses. LINE can then deliver the same event more than once and change the order, so rely on event IDs. - LINE accepts one endpoint per channel. Don't append the Destination ID, the Channel ID, a project ID, or any connection identifier, because Artemis routes from the signed body rather than the path. +Use the generic LINE URL exactly as shown. Don't append the Destination ID, Channel ID, project ID, or a connection identifier. LINE puts `destination` in the signed body, and Artemis routes from that value. - LINE also requires HTTPS with a certificate from a widely trusted authority. Self-signed certificates fail, and so does a server missing its intermediate certificates, which is a common cause of a verification failure that looks like a LINE problem. - - - - Click **Verify**. LINE posts an event-free payload to the endpoint, and Artemis responds once it has resolved the connection and verified the signature. LINE reports **Success** when this works. - - Treat anything else as a stop. A timeout, a non-200 response, a TLS error, and a signature failure each point somewhere different, and continuing past one means debugging later with live users watching. - - - - Turn on **Use webhook**. - - This is the step people miss. Saving a verified URL without this toggle leaves the channel looking correctly configured while message events never reach Artemis. - - - - Enable redelivery only when your operations policy requires retries after a non-2xx response. - - LINE can deliver the same webhook more than once when redelivery is on, and it can change event order during redelivery. Your agent logic has to tolerate both, so rely on event IDs rather than arrival order before you turn this on. - - - - The channel's **Security** tab accepts a list of IP addresses, individually or in CIDR notation, that may call the LINE Platform with a long-lived token. - - This narrows the blast radius of an indefinite credential considerably, so it's worth doing whenever you pick that token type. LINE covers the setting under [restrict who can call the API](https://developers.line.biz/en/docs/messaging-api/building-bot/#configure-security-settings). It doesn't apply to the other three. - - +If you use a long-lived token, restrict API callers by IP address on the channel's **Security** tab. See [configure security settings](https://developers.line.biz/en/docs/messaging-api/building-bot/#configure-security-settings). ### Validation checklist +Work down this list once per connection. + | Validation item | Expected result | |:---|:---| -| Complete LINE setup | Official Account created, Messaging API enabled, and greeting and auto-reply messages disabled. | -| Collect credentials | Channel Secret, Channel Access Token, and the `U`-prefixed Destination ID copied from the matching channel. | -| Create the Artemis connection | Connection saved as **Active** with the Destination ID, both credentials, and the intended environment. | -| Register the webhook URL | LINE reports **Success** when you click **Verify**. | -| Enable delivery | **Use webhook** shows as turned on. | -| Send a live message | A real LINE conversation produces exactly one agent reply. See [Verify the connection](#verify-the-connection). | +| Prepare the account | Messaging API enabled under the right provider, with automatic replies reviewed. | +| Collect credentials | Channel Secret, Channel Access Token, and the `U`-prefixed Destination ID from the same channel. | +| Create the Artemis connection | Saved as **Active**. | +| Verify the webhook | LINE reports **Success**. | +| Turn on delivery | **Use webhook** is on. | +| Send a live message | One real conversation produces exactly one agent reply. | + +--- ## Verify the connection Artemis has no synthetic test for this channel, so a real conversation is the only end-to-end proof. -1. Add the Official Account as a friend by scanning the QR code or using the add-friend link on the **Messaging API** tab. Test from an ordinary LINE account rather than an identity that exists only as a console administrator, because the two behave differently. -2. Send a short message you can search for later, and confirm the agent replies in the same chat. -3. Count the replies. Two responses to one message means greeting messages or auto-reply messages are still enabled, not that the agent ran twice. -4. Send each input type your agent supports, and confirm its authored behavior for each. Receiving a media event isn't the same as handling it, so test the authored path rather than only the delivery. -5. Test groups only if you need them. Enable **Allow bot to join group chats** in Official Account Manager, invite the bot, then message or mention it. Confirm sessions stay scoped to the LINE source, so a group conversation and a one-to-one conversation with the same person don't merge. - ---- - -## Secure the connection +1. Add the Official Account as a friend with the QR code or add-friend link on the **Messaging API** tab. Test from a normal LINE account, not an administrator-only console identity. +2. Send a unique text message. +3. Confirm the agent replies once in the same chat. A LINE auto-reply plus an agent reply means the response settings are still on. +4. Test each input type you intend to support. Receiving a media event doesn't guarantee the agent flow knows how to use the attachment. +5. If you need groups, turn on **Allow bot to join group chats** in Official Account Manager, invite the bot, message or mention it, and confirm sessions stay scoped to the LINE source. -Both LINE credentials are secrets, and they do opposite jobs. The Channel Secret authenticates what comes in; the Channel Access Token authorizes what goes out. +| Input | What to confirm | +|---|---| +| `text` | The agent receives and answers it. | +| `image`, `video`, `audio`, `file` | The token downloads the content and the agent processes it. | +| `location`, `sticker` | The agent's authored behavior handles the event. | +| `postback` | The action returns to the same session. | -Artemis computes HMAC-SHA256 over the unchanged raw request body and compares it with the `X-Line-Signature` header. Any proxy or middleware in front of Artemis has to leave the signed body untouched, because a single changed byte fails verification as surely as a wrong secret does. +--- -Rotation invalidates immediately on both credentials. Reissuing a Channel Secret kills the old secret, and reissuing a long-lived access token kills the previous token unless you use the 24-hour extension. Coordinate the Artemis update with the provider-side change rather than doing them hours apart. Revoke any token you suspect someone has copied, because a compromised token can broadcast to every friend of the Official Account. +## Security and credential boundaries -Keep both values out of browser code, screenshots, tickets, and source control, and update Artemis the moment LINE reissues or revokes either one. +The Channel Secret authenticates what comes in. The Channel Access Token authorizes what goes out. -Use distinct providers or channels for development and production, or at minimum distinct credentials and connections. Pointing two environments at one webhook mixes test traffic into real conversation history. +- **Signatures**: Artemis computes HMAC-SHA256 over the unchanged raw body and compares it with `X-Line-Signature`. +- **Raw bytes**: Proxies and middleware must not rewrite the signed body. A changed byte, wrong secret, or reissued secret fails authentication. +- **Rotation**: Reissuing a Channel Secret invalidates the old one. Reissuing a long-lived token invalidates the previous token. Coordinate the Artemis update with the LINE change. +- **Environments**: Use distinct providers or channels, or at least distinct credentials and connections, for development and production. Never point two environments at the same webhook. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **LINE** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to register in the Developers Console and the **Destination ID** this connection matches events to, each with a copy control. Check the Destination ID here first when messages arrive and no session appears. - +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **LINE** and **Channel Connection**. | +| **Identifier** | The Destination ID this connection routes on. Check it first when messages arrive and no session appears. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The webhook URL for LINE, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + - Artemis encrypts credentials after you save them, so each field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new one to replace it. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credentials from a saved auth profile instead of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | **Channel Access Token** | Replace it here whenever you reissue the token in the Developers Console, and do it promptly, because the old token stops working at once. | - | **Channel Secret** | Replace it here if another administrator reissues the secret. Until you do, every inbound event fails signature verification. | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **Channel Access Token** | Replace it promptly when you reissue the token, because the old one stops working. | + | **Channel Secret** | Replace it if an administrator reissues the secret. Until you do, every inbound event fails verification. | - Click **Save Credentials** to apply your changes. + Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this Official Account changes. - - Under **LINE Settings**, **Destination ID** appears read-only. Artemis routes inbound events by this value, so changing it would orphan the connection. Create a new connection to serve a different Official Account. + Update how the connection behaves. **LINE Settings** holds the provider-specific fields. - **Authorization Message** controls what the person sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts LINE's identity assertion. | + | **Destination ID** | Read-only, with a copy control. To serve another Official Account, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The webhook URL, with a copy control. | - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | - - Item variables resolve only inside the repeat block. Use the preview to check the wording, and remember it fills from live pending authorizations at runtime. - - Click **Save Changes** to apply your changes. + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers LINE. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic and when someone deployed it. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Check this pair when the channel connects but the agent behaves like an older build. The connection follows whatever the environment currently has deployed, not the version you last edited. Click **Save Changes** after you switch the environment. + Select **Save Changes** after you switch the environment. @@ -305,36 +250,34 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Most failures trace to the Destination ID, the Channel Secret, or the **Use webhook** toggle. + | Symptom | Likely cause | Recommended action | |---|---|---| -| Verify doesn't report success | The connection isn't active, the endpoint isn't reachable, or the certificate chain is incomplete | Confirm the connection exists and is active, that the Artemis endpoint is reachable over public HTTPS with a certificate from a trusted authority and a complete chain, that the URL carries no extra path segment, and that LINE receives a 200 response. | -| Artemis reports no connection found | The Destination ID holds the wrong identifier | Replace it with the `U`-prefixed `userId` from Get bot info. The Channel ID, the Bot basic ID, and personal user IDs don't route. | -| Signature verification fails | The Channel Secret doesn't match, or a proxy rewrote the body | Copy the Channel Secret from the matching channel's **Basic settings**, check whether another administrator reissued it, and confirm no proxy or middleware rewrites the raw body. | -| Verification succeeded but no messages arrive | **Use webhook** is off | Turn on **Use webhook**. A saved and verified URL delivers nothing until you do. | -| Messages arrive but the agent doesn't reply | The access token expired, someone revoked it, or no deployment can run | Confirm the Channel Access Token is current, the connection is active, and the bound environment has a runnable deployment. A v2.1 token past its 30-day ceiling produces exactly this symptom. | -| People receive two replies | LINE's own automatic replies are still enabled | Disable greeting messages and auto-reply messages, or author them so they don't overlap with the agent. | -| Direct messages work but groups don't | The bot can't join group chats, or it joined before you changed the setting | Enable **Allow bot to join group chats**, reinvite the bot if you changed the setting after inviting it, and confirm the test event comes from the expected group or room. | -| Text works but media doesn't | The event type, the token, the size limit, or the agent flow blocks it | Confirm Artemis supports the event type, the token can download message content, attachment limits allow the file, and the agent flow handles attachments. | -| The provider you want isn't in the list | Your account lacks the admin role on it | Ask a provider admin to grant the role rather than creating a second provider. | +| **Verify** doesn't show **Success** | No active connection, unreachable endpoint, or bad URL | Confirm the connection exists and is **Active**, the endpoint is reachable over trusted public HTTPS, the URL has no extra path segment, and LINE gets a `200` response. | +| No connection found | Wrong identifier saved | Replace the Destination ID with the `U`-prefixed `userId` from Get bot info. The Channel ID, Basic ID, and personal user IDs don't route. | +| Signature verification fails | Wrong or reissued secret, or a rewritten body | Copy the Channel Secret from the matching channel's **Basic settings**, check whether another admin reissued it, and confirm no proxy changes the raw body. | +| Verified but no messages arrive | **Use webhook** is off | Turn on **Use webhook**. | +| Messages arrive but the agent doesn't reply | Token or deployment issue | Check that the Channel Access Token is current, the connection is **Active**, the environment has a runnable deployment, and LINE hasn't revoked or expired the token. | +| Users receive two replies | LINE automatic replies still on | Turn off or deliberately coordinate **Greeting messages** and **Auto-reply messages** in Official Account Manager. | +| Direct messages work but groups don't | The bot can't join groups | Turn on **Allow bot to join group chats**, reinvite the bot if necessary, and confirm the test event comes from the expected group or room. | +| Text works but media doesn't | Unsupported type, token, or policy | Confirm Artemis supports the event type, the token can download message content, attachment limits allow the file, and the agent flow handles attachments. | --- ## LINE reference -Use these LINE pages and consoles when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. Artemis field names and the runtime URL shown in the connection stay the source of truth for this integration. | Resource | Use it for | -| -------- | ---------- | -| [LINE Official Account Manager](https://manager.line.biz/) | Creating the Official Account, enabling the Messaging API, response settings, group chat permission, and admin roles. | -| [LINE Developers Console](https://developers.line.biz/console/) | Channel credentials, webhook settings, the security tab, and the friend-add QR code. | -| [Get started with the Messaging API](https://developers.line.biz/en/docs/messaging-api/getting-started/) | LINE's own walkthrough of Business ID registration, account creation, and provider selection. | -| [Build a bot](https://developers.line.biz/en/docs/messaging-api/building-bot/) | Tokens, the webhook URL, verification, and the certificate requirements. | -| [Channel access tokens](https://developers.line.biz/en/docs/basics/channel-access-token/) | How the four token types differ and which suits your rotation policy. | -| [Messaging API reference](https://developers.line.biz/en/reference/messaging-api/) | Endpoint detail, including [Get bot info](https://developers.line.biz/en/reference/messaging-api/#get-bot-info) and webhook event objects. | +|---|---| +| [Build a LINE bot](https://developers.line.biz/en/docs/messaging-api/building-bot/) | Tokens, the webhook URL, verification, and certificate requirements. | +| [Verify webhook signatures](https://developers.line.biz/en/docs/messaging-api/receiving-messages/#verify-signature) | How `X-Line-Signature` works. | +| [Channel access tokens](https://developers.line.biz/en/docs/basics/channel-access-token/) | How the token types differ. | +| [Messaging API reference](https://developers.line.biz/en/reference/messaging-api/) | Get bot info and webhook event objects. | {{related}} - [Channels](/agent-platform/channels) - [Set up Messenger](/agent-platform/channels/messenger) -- [Set up WhatsApp](/agent-platform/channels/whatsapp) - [Set up Telegram](/agent-platform/channels/telegram) \ No newline at end of file diff --git a/agent-platform/channels/messenger.mdx b/agent-platform/channels/messenger.mdx index 759018c26..d95f65fe9 100644 --- a/agent-platform/channels/messenger.mdx +++ b/agent-platform/channels/messenger.mdx @@ -3,127 +3,91 @@ title: Set up Messenger sidebarTitle: Messenger --- -[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect a Facebook Page to your agent so people reach it through Messenger. You prepare one Meta app and one Page, hand Artemis four values from them, then register a signed webhook that Meta verifies before it sends anything. +Connect a Facebook Page to your agent so people reach it through Messenger. You prepare one Meta app and one Page, enter four values in Artemis, then register a signed webhook that Meta verifies. The setup requires: -1. [Meta setup](#meta-setup): create a business app, connect the Page, and collect the Page ID, Page Access Token, and App Secret. -2. [Artemis channel configuration](#artemis-channel-configuration) using those values plus a Verify Token you invent, then copy the generated webhook URL. -3. [Webhook configuration in Meta](#webhook-configuration-in-meta): register the callback URL, complete Meta's challenge, and subscribe the Page to the message events. +1. [Meta setup](#meta-setup): prepare the app and Page, and collect four values. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +3. [Webhook configuration in Meta](#webhook-configuration-in-meta): verify the callback and subscribe the Page. +4. [Verify the connection](#verify-the-connection) with a real two-way conversation. -After you complete the configuration, Meta posts signed Page events to Artemis, which matches the Page ID in the payload to this connection and hands the message to the deployed agent. +After setup, Meta posts signed Page events to Artemis. Artemis matches the Page ID in each event to the connection, and the agent replies in the same Messenger conversation. **Important considerations** -- **Every value must come from one app and one Page**: The Page ID, Page Access Token, App Secret, Verify Token, and webhook subscription all have to belong to the same Meta app and Page setup. Mixing values from two apps produces failures that look unrelated to each other. -- **One Page routes to one connection**: Reusing a Page means deactivating the existing connection first, or the second one has nothing to route to. -- **Verification and subscription are separate steps**: Meta verifies the callback URL whether or not you subscribe to anything, so a verified webhook with no subscription looks correct on screen and delivers nothing. -- **Development mode blocks the public**: Until Meta approves the app and you switch it to Live, Page tokens reach only accounts holding an app or Page role. A successful test with a role-holding account proves nothing about public access. - -The Meta work spans three screens in the App Dashboard at [Meta for Developers](https://developers.facebook.com/). - -| Meta screen | What you do there | -| ----------- | ----------------- | -| Messenger settings | Connect the Page, generate the Page Access Token, and configure the webhook. | -| **App settings** -> **Basic** | Reveal and copy the App Secret. | -| **Roles** tab | Add the testers who can reach your Page before app review. | +- **The Facebook Page ID selects the connection**: Artemis reads `entry[0].id` from each webhook and matches it to the saved Page ID. The Page ID, Page Access Token, App Secret, Verify Token, and webhook subscription must all belong to the same Meta app and Page. +- **One Page routes to one active connection**: To reuse a Page, deactivate the old connection first. +- **Verification and subscription are separate steps**: Meta verifies the callback whether or not you subscribe to anything, so a verified webhook with no subscription delivers nothing. +- **Development success doesn't prove public access**: A role-based tester can reach the Page while ordinary visitors can't. Test again with a non-role account after Meta approves the app and you switch it to Live. ## Prerequisites -- A Meta developer account, and a Facebook Page that customers will message. -- Enough access on the Page to perform the messaging and moderate tasks. Meta requires this of whoever generates the Page Access Token, so an editor or viewer role fails even when the app side looks correct. -- An HTTPS-reachable Artemis runtime, since Meta calls the callback URL during verification. +Confirm these before you start. + +- A Meta developer account and the Facebook Page customers will message. +- Page access that covers the messaging and moderate tasks. An editor or viewer role can't generate a working Page token. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- ## How Artemis routes Messenger events -Meta sends every Page event to one generic URL, so Artemis identifies the connection from the payload rather than the path. It reads the Page ID out of the signed event and matches it to a connection. +Meta sends every Page event to one generic URL, so Artemis identifies the connection from the signed payload. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Facebook Page ID** | Meta | Routes inbound events. Artemis reads the Page ID from each signed webhook and matches it to this connection. | -| **Page Access Token** | Meta | Authorizes outbound replies through the Messenger Send API. It scopes to one Page, so a token for a different Page fails to send. | -| **App Secret** | Meta | Verifies the `X-Hub-Signature-256` header on every inbound POST. Artemis computes the HMAC over the unchanged request body and rejects anything that doesn't match. | -| **Verify Token** | You | Answers Meta's one-time verification challenge when you save the callback URL. It does nothing after that. | -| **Webhook URL** | Artemis | Receives events. The route ends at the generic Messenger path and carries no Page ID, because the Page ID travels in the payload. | +| Piece | Owner | What it does | +|---|---|---| +| **Facebook Page ID** | Meta | Routes inbound events by matching `entry[0].id`. | +| **Page Access Token** | Meta | Authorizes replies through the Messenger Send API, as a Bearer token. It's scoped to one Page. | +| **App Secret** | Meta | Validates `X-Hub-Signature-256` over the unchanged request body. | +| **Verify Token** | You | Answers Meta's one-time verification challenge. | +| **Webhook URL** | Artemis | Receives events at `/api/v1/channels/messenger/webhook`, with no Page ID in the path. | --- ## Meta setup -Complete all of this in Meta before you open Artemis. Meta covers the same ground in its [Messenger Platform quick start](https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start/). +Do this in Meta before you open Artemis. Select **Open Meta apps** in the setup guide to jump straight there. Meta covers the same ground in its [Messenger Platform quick start](https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start/). - 1. Sign in to [Meta for Developers](https://developers.facebook.com/) and open [My Apps](https://developers.facebook.com/apps/). - 2. Create an app, or open the one that will own this connection. - 3. When Meta asks what the app does, choose the business messaging use case, or choose **Other** and then **Business** as the app type if Meta shows you that older flow. - - Only a business app exposes the Messenger product, so choosing the wrong type means creating a second app rather than converting the first. - - Use separate apps or Pages for development and production, because app mode and Page subscriptions belong to the app. + 1. In [My Apps](https://developers.facebook.com/apps/), create an app suitable for your business integration, or open the one that will own this connection. + 2. Use separate apps or Pages for development and production. - 1. On the App Dashboard, find **Messenger** in the products list. - 2. Click **Set up**. The left menu then carries a Messenger section holding the settings screen you'll return to several times. - - Meta renames this screen between app types, so you may see **Messenger API Settings**, or **Messenger** followed by **Settings**. Whichever label appears, the screen you want holds three areas together: a Page connection, a token generation panel, and webhook controls. If the screen you're looking at has only one of those, you're on the wrong one. + Add **Messenger** to the app and open **Messenger API Settings**. Labels vary by app type, but the screen must show a Page connection, token generation, and webhook controls. - 1. In the token generation area, add or select the Page customers will message. - 2. Authorize the app on that Page when Meta asks. - - Your account needs enough access on both sides. Meta requires that whoever generates the Page token can perform the messaging and moderate tasks on the Page, so an editor or viewer role fails here even when everything on the app side looks right. Sort the Page role out before you continue, because the failure it produces later looks like a token problem. + Add or select the Page customers will message, and authorize the app on it. Confirm your account has enough Page and app permissions before you generate credentials. - - 1. Select the Page in the **Page** dropdown. A token appears in the **Page Access Token** field. - 2. Click the field to copy the token. - - Two behaviors here catch people out. Meta doesn't store the token in this screen, so you can't come back and read it; you generate a fresh one instead. And each time you select the Page from the dropdown, Meta generates a new token, while every token it generated earlier keeps working. That means an accidental extra generation doesn't break anything, but it does leave live credentials you didn't intend to create, so treat each generation as deliberate. + + Select the Page in the token generation area and copy the token. Meta doesn't store it on this screen, and each new selection generates another token while earlier tokens keep working. - This token is Page-scoped rather than user-scoped. A user token, or a token generated for a different Page, authenticates successfully and then fails to deliver replies. + A user token or a token for another Page authenticates but can't send replies. - - Artemis routes on the Page's numeric ID, which is a different value from everything else Meta shows you about the Page. + + Copy the Page ID shown for the Page connected under **Messenger API Settings**. You can also find it under the Page's **About** information or in [Meta Business Suite](https://business.facebook.com/). - 1. Open the Page in Facebook and look under its **About** information, where Facebook lists the Page ID among the page's transparency details. - 2. Or open the Page's settings in [Meta Business Suite](https://business.facebook.com/), which also shows it. - - Don't substitute the Meta App ID, the Business ID, the Page username from the Page's web address, or the page-scoped user ID. That last one, the PSID, appears in every inbound event and identifies the customer, not the Page: Meta issues each person a different PSID for each Page they message. + Don't use the Meta App ID, Business ID, Page username, or a customer's PSID. - The App Secret sits outside the Messenger section, so the left menu is the only route to it. - 1. Go to **App settings** -> **Basic**. - 2. Click **Show** beside **App secret**. - 3. Re-enter your Facebook password when Meta asks, then copy the value. - - Artemis uses this secret to verify that an inbound event genuinely came from Meta. Take it from the same app that owns the Messenger product, since an App Secret from a neighboring app produces a signature failure on every single message. + 2. Select **Show** beside **App secret**, re-enter your password, and copy the value. - Invent a high-entropy secret string. Meta doesn't issue this one, so you create it and enter the same value twice: once in Artemis, once in the Meta webhook configuration. - - Artemis lets you save a connection without it, but Meta's verification can't succeed until a matching non-empty value exists in both places. + Create a high-entropy secret string. Artemis saves a connection without it, but Meta verification fails until the same non-empty value exists in Artemis and Meta. - - While the app stays in development mode, Page tokens reach only Facebook accounts holding an administrator, developer, or tester role on the app. - - 1. Grant those roles from the **Roles** tab of your app settings, which Meta describes under [standard access](https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start/). - 2. Have each person accept the invitation before you test with them. - 3. Before ordinary customers can message the Page, submit the app for review on the messaging permissions and complete business verification. Then switch the app to Live mode using the control at the top of the App Dashboard. - - A successful test with a role-holding account proves nothing about public access. Plan to repeat it with an account holding no role once the app goes Live. + + In development mode, only people with an app or Page role can test. Before public traffic, complete app review, business verification, permissions, and the Live-mode requirements Meta shows for your app. @@ -131,177 +95,153 @@ Complete all of this in Meta before you open Artemis. Meta covers the same groun ## Artemis channel configuration -Create the connection before you configure the callback in Meta. Meta sends its verification request the moment you save the webhook, and Artemis can only answer that challenge from a stored Verify Token. +Create the connection before you configure the callback in Meta. Artemis resolves Meta's challenge from the stored Verify Token. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **Messenger** -> **+ New**. The **New Messenger Connection** dialog opens. -3. Configure the following fields: +2. Go to **Deployments** -> **Channels** -> **Messenger** -> **+ New**. The **New Messenger Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: - | Artemis connection field | Source / Notes | What it controls | + | Artemis field | Source / Notes | What it controls | |---|---|---| - | Display Name | You choose it | The label operators see in the connections list. Name it for the Page and the environment it serves, because a project can hold several Messenger connections. Routing ignores this value. | - | Facebook Page ID | The Page's **About** information, or Meta Business Suite. See [Meta setup](#meta-setup). | The routing key. It's numeric, and it isn't the App ID, Business ID, Page username, or PSID. | - | Page Access Token | Messenger settings > token generation panel | The credential for outbound replies. Generate it for this exact Page. | - | App Secret | **App settings** -> **Basic** in the same Meta app | The key Artemis uses to verify the signature on every inbound event. | - | Verify Token | You invent it | Answers Meta's one-time verification challenge. Enter the identical value in Meta when you register the callback. | - | Environment | Your published environments | The environment whose active deployment answers incoming messages. Leave the working copy default only while you develop. | - | Provider Verification Strength | Defaults to **Weak** | How far Artemis trusts Meta's identity assertion when it links a person to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Defaults to **Active** | Whether the connection starts handling messages. Set it to **Active**, because Meta's verification challenge resolves only when the connection is already active. | - -4. Click **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab. You need it for the next section. + | **Display Name** | You choose it | The label operators see. Name it for the Page and environment. Routing ignores it. | + | **Facebook Page ID** | **Messenger API Settings** | The routing key, matched to `entry[0].id`. | + | **Page Access Token** | The token generation area | Authorizes replies through the Send API. Generate it for this exact Page. | + | **App Secret** | **App settings** -> **Basic** | Validates `X-Hub-Signature-256` over the unchanged body. | + | **Verify Token** | You create it | Answers Meta's verification challenge. | + | **Environment** | Your published environments | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Meta's identity assertion when it links a person to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | Keep it **Active**. Meta's challenge resolves only for an active connection. | + +4. Select **Create**. +5. Copy the **Webhook URL** from the connection's summary panel. --- ## Webhook configuration in Meta -Registration has two halves, and completing only the first is the most common way a setup fails silently. Meta verifies the URL whether or not you subscribe to anything. - - - - 1. Return to the Messenger settings screen in the same Meta app. - 2. Find the webhooks area and add a callback for the Page object. - - Configure the URL here rather than under another Meta product. A callback registered under a different product verifies successfully and delivers nothing to this connection, which is a slow failure to trace because both screens report success. - - - - 1. Paste the Artemis **Webhook URL** exactly as shown. - 2. Enter the same **Verify Token** you saved in Artemis. - - Don't append a Page ID, a connection ID, a query string, or a trailing segment. Artemis takes the Page ID from the signed payload, so anything added to the path breaks the route rather than refining it. - - - - Save the callback. Meta immediately calls the URL with a subscribe challenge and expects your Verify Token echoed back. +Registration has two halves. Complete both in the same Meta app. - Artemis answers only when the token matches an active connection, so a failure here points at the token, the connection status, or public reachability over HTTPS rather than at the URL itself. - - - - 1. In the webhook fields list, click **Manage**. - 2. Subscribe the Page webhook to `messages` and `messaging_postbacks`. - - The `messages` field carries text, attachments, and quick-reply payloads, so it's required even for an agent that only handles text. Subscribe `messaging_postbacks` as well if your agent sends buttons, since a button tap arrives as a separate event type carrying the authored payload rather than as a message. - - - - 1. Confirm this app and webhook list the intended Page as subscribed. - 2. Save the app changes. - - If Meta asks for permissions review or Page task access for your current app mode, complete that before you test with anyone outside your app roles. - - +1. Confirm the Artemis connection is **Active**. Meta sends the verification request as soon as you save the callback. +2. Open **Messenger API Settings** or **Webhooks**, and add a callback for the **Page** object. Don't configure it under an unrelated Meta product. +3. Paste the Artemis **Webhook URL** and the same **Verify Token**. Don't append a Page ID, connection ID, query string, or trailing segment. +4. Save. Meta sends `hub.mode=subscribe`, `hub.verify_token`, and `hub.challenge`, and Artemis returns the challenge only when the token matches an active Messenger connection. +5. Subscribe the Page webhook to `messages` for text, attachments, and quick replies, and `messaging_postbacks` for button actions. +6. Confirm this app and webhook list the intended Page as subscribed, and save the app changes. Complete any permissions review or Page task access Meta requires for your app mode. ### Validation checklist +Work down this list once per connection. + | Validation item | Expected result | |:---|:---| -| Complete Meta setup | Business app created, Messenger product added, and the Page connected with a generated Page Access Token. | -| Collect credentials | Numeric Page ID, Page Access Token, and App Secret copied from the same app and Page. | -| Create the Artemis connection | Connection saved as **Active** with all four values and the intended environment. | -| Register the callback URL | Meta accepts the callback and completes the verification challenge. | -| Subscribe the events | This app and webhook list the Page as subscribed to `messages` and `messaging_postbacks`. | -| Send a live message | A real Messenger conversation produces exactly one agent reply. See [Verify the connection](#verify-the-connection). | -| Retest after Live mode | An account with no app or Page role reaches the agent. | +| Complete Meta setup | Business app, Messenger product, connected Page, and a Page Access Token. | +| Create the Artemis connection | Saved as **Active** with all four values from the same app and Page. | +| Register the callback | Meta completes the verification challenge. | +| Subscribe the events | The Page subscribes to `messages` and `messaging_postbacks`. | +| Send a live message | One real conversation produces exactly one agent reply. | +| Retest after Live | An account with no app or Page role reaches the agent. | + +--- ## Verify the connection Artemis doesn't synthesize Meta events, so a real Messenger conversation is the only end-to-end proof. -1. While the app sits in development mode, use a Facebook account holding an app or Page role. Open the connected Page in Messenger and send a short message you can search for later. Confirm Meta reports a successful webhook delivery and that Artemis opens one session. -2. Check that a single outbound reply appears in the same conversation. A send failure at this point usually means the token belongs to the wrong Page, the messaging permission is missing, someone revoked the token, or the app mode still restricts delivery. -3. Trigger a quick reply and a button postback, and confirm each returns to the same session. Artemis normalizes both into action events, so the authored action ID and value still have to exist in the agent. -4. Send each message type your Page will use. Artemis downloads image, video, audio, and file attachments before the agent processes them. Location, sticker, and fallback attachments arrive as events rather than as files, so an agent that expects a downloadable attachment won't find one. -5. Once Meta approves the app and you switch it to Live mode, run the same test from an account with no app or Page role. This is the only check that proves ordinary customers can reach the agent. +1. While the app is in development mode, use a Facebook account with an app or Page role. +2. Open the Page in Messenger and send a unique message. Confirm Meta reports a successful delivery and Artemis creates one session. +3. Confirm one reply appears in the same conversation. A send failure usually means a token for the wrong Page, a missing permission, expired or revoked access, or an app-mode restriction. +4. Trigger a quick reply and a button postback. Artemis normalizes both into action events, so the authored action ID and value must still exist in the agent. +5. Test each message type the Page uses. After review and Live mode, repeat the test with a non-role account. + +| Input | What to confirm | +|---|---| +| `text` | The agent receives and answers it. | +| `image`, `video`, `audio`, `file` | Artemis downloads the attachment before the agent processes it. | +| `quick replies`, `postbacks` | The action returns to the same session. | +| Location, sticker, fallback | These arrive as events, not files, so the agent gets no download. | --- ## Messenger limits -Meta enforces these boundaries on outbound content, and Artemis applies them before it calls the Send API. Design your agent's responses to fit them. +Artemis applies these limits before it calls the Send API. | Area | Limit | -| ---- | ----- | -| Buttons | Button templates carry up to 3 buttons, with titles capped at 20 characters. | -| Quick replies | Up to 13 choices, with titles capped at 20 characters. | -| Carousels | Generic-template carousels carry up to 10 cards and up to 3 buttons per card. | -| Postback payloads | Up to 1,000 characters, which is the authored value your agent branches on. | -| Messaging window | Meta's standard messaging window lets you reply freely for 24 hours after a person messages the Page. Outside it, you need an approved message tag, which the [Send API reference](https://developers.facebook.com/docs/messenger-platform/reference/send-api/) lists. A valid Page Access Token doesn't bypass this. | -| Media | Remote media has to stay reachable from Artemis and within attachment size, content-type, and network-safety policies. | +|---|---| +| Buttons | Up to 3 per button template, with titles up to 20 characters. | +| Quick replies | Up to 13 choices, with titles up to 20 characters. | +| Carousels | Up to 10 generic-template cards, with up to 3 buttons per card. | +| Policy | Meta messaging windows, message tags, and platform policies still apply. A valid Page Access Token doesn't bypass recipient or timing rules. | +| Media | Remote media must stay reachable from Artemis, and within download size, content-type, and network-safety policies. | --- -## Secure the connection - -Messenger authentication runs in one direction only, which is easy to misread. Meta signs what it sends you; your Verify Token does nothing after setup. +## Security and secret boundaries -Every Messenger POST carries `X-Hub-Signature-256`. Artemis computes HMAC-SHA256 over the raw request body using your App Secret and rejects a missing or mismatched signature. Any proxy or middleware in front of Artemis has to preserve the exact request bytes, because reformatting the JSON changes the digest even when the content stays identical. +Meta signs what it sends. Your Verify Token only protects the one-time challenge. -Keep the three secrets distinct in your own operational notes. The Verify Token protects only the initial challenge and is a string you invented. The App Secret authenticates inbound traffic. The Page Access Token authorizes outbound sends, and you can rotate it without touching the Page ID, so a token rotation never requires a new connection. - -Artemis rejects Messenger events older than five minutes as replay protection. Replaying a captured payload during debugging therefore fails by design, and a live message is the only way to retest. - -Use separate Meta apps or Pages, credentials, callbacks, and connections for development and production. +- **Signatures**: Every Messenger POST must include `X-Hub-Signature-256`. Artemis computes HMAC-SHA256 with the saved App Secret and rejects a missing or mismatched signature. +- **Raw bytes**: Proxies and middleware must preserve the exact request bytes. Reformatting JSON changes the digest. +- **Verify Token**: A user-generated shared secret, separate from the App Secret and the Page Access Token. +- **Page Access Token**: Authorizes outbound Send API calls. Store it only in Artemis, and rotate it without changing the Page ID. +- **Replay protection**: Artemis rejects Messenger events older than five minutes. +- **Environments**: Use separate Meta apps or Pages, credentials, callbacks, and connections for development and production. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **Messenger** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to register in Meta and the **Facebook Page ID** this connection matches events to, each with a copy control. Check the Page ID here first when messages arrive and no session appears. - +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Messenger** and **Channel Connection**. | +| **Identifier** | The Facebook Page ID this connection routes on. Check it first when messages arrive and no session appears. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The callback URL for Meta, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + - Artemis encrypts credentials after you save them, so each field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new one to replace it. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credentials from a saved auth profile instead of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | **Page Access Token** | Replace it here when you generate a new token in Meta. The Page ID stays the same, so you don't need a new connection. | - | **App Secret** | Replace it here if you move the Messenger product to a different Meta app. | - | **Verify Token** | Changing this breaks Meta's webhook until you enter the matching value in Meta as well. | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **Page Access Token** | Replace it when you generate a new token in Meta. | + | **App Secret** | Replace it if the Messenger product moves to another Meta app. | + | **Verify Token** | Changing it breaks the Meta webhook until you enter the same value in Meta. | - Click **Save Credentials** to apply your changes. + Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this Page changes. - - Under **Messenger Settings**, **Facebook Page ID** appears read-only. Artemis routes inbound events by this value, so changing it would orphan the connection. Create a new connection to serve a different Page. - - **Authorization Message** controls what the person sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. + Update how the connection behaves. **Messenger Settings** holds the provider-specific fields. - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Meta's identity assertion. | + | **Facebook Page ID** | Read-only, with a copy control. To serve another Page, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The callback URL, with a copy control. | - Item variables resolve only inside the repeat block. Use the preview to check the wording, and remember it fills from live pending authorizations at runtime. - - Click **Save Changes** to apply your changes. + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers Messenger. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic and when someone deployed it. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Check this pair when the channel connects but the agent behaves like an older build. The connection follows whatever the environment currently has deployed, not the version you last edited. Click **Save Changes** after you switch the environment. + Select **Save Changes** after you switch the environment. @@ -309,34 +249,34 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Most failures trace to mismatched values or a missing subscription. + | Symptom | Likely cause | Recommended action | |---|---|---| -| Callback verification fails | The connection doesn't exist yet, the Verify Tokens don't match, or the endpoint isn't publicly reachable | Create the connection before you save the callback, enter the same non-empty Verify Token in both systems, use the URL exactly as Artemis shows it, and confirm the endpoint is reachable over public HTTPS. | -| Inbound requests return 401 | The App Secret came from a different Meta app, or a proxy altered the signed request | Copy the App Secret from the app that sends the webhook, and confirm every proxy preserves the original request body and the `X-Hub-Signature-256` header. | -| Artemis reports no connection found | The Facebook Page ID field holds the wrong identifier | Compare the Page ID in the webhook payload with the numeric value saved in Artemis, and confirm the connection is active. A PSID or an App ID in this field produces exactly this result. | -| Verification succeeded but no messages arrive | The webhook has no field subscription, or the Page isn't subscribed to the app | Subscribe the `messages` and `messaging_postbacks` fields, confirm the app lists the intended Page as subscribed, and check the app mode, tester roles, and outstanding permissions. | -| Messages arrive but replies fail | The token is for the wrong Page, the Page role is insufficient, or no deployment can run | Generate a fresh Page Access Token for the same Page, confirm your account can perform the messaging and moderate tasks on the Page, and confirm the bound environment has a runnable deployment. | -| Everything works for your team and nobody else | The app is still in development mode | Complete app review and business verification, switch to Live, then retest from an account with no role. | -| Text works but buttons fail | The content exceeds a Messenger limit, or the authored action is gone | Keep button and quick-reply counts and label lengths within the limits above, then confirm the authored action still exists in the agent. | -| Text works but attachments fail | The media is unreachable, disallowed, or oversized | Confirm the attachment URL is reachable, that policy allows its host, content type, and size, and that the agent handles the downloaded file. | -| Artemis ignores replayed events | Replay protection rejects events older than five minutes | Expected behavior. Send a new live message instead of replaying a captured payload. | +| Callback verification fails | No active connection, mismatched token, or unreachable endpoint | Create the connection first, enter the same non-empty Verify Token in both systems, use the generic Messenger route, and expose public HTTPS. | +| POST requests return `401` | Wrong App Secret or altered request | Copy the App Secret from the app that sends the webhook, and confirm every proxy preserves the body and `X-Hub-Signature-256`. | +| No connection found | Wrong identifier saved | Compare `entry[0].id` with the saved numeric Page ID, and confirm the connection is **Active**. | +| Verified but no messages arrive | Missing subscription or app-mode restriction | Subscribe `messages` and `messaging_postbacks`, subscribe the Page to the app, and check app mode, tester roles, and permissions. | +| Messages arrive but replies fail | Wrong token or no runnable deployment | Regenerate a Page Access Token for the same Page, verify messaging permission and policy eligibility, and confirm the environment can run. | +| Text works but buttons fail | Content outside Messenger limits | Keep button and quick-reply counts and label lengths within limits, and confirm the authored action exists. | +| Text works but attachments fail | Media outside policy | Confirm the attachment URL is reachable, policy allows its host and content type, its size is within policy, and the agent handles the file. | +| Artemis ignores old retries | Replay protection | Expected behavior for events older than five minutes. Send a new live message instead of replaying a payload. | --- ## Meta reference -Use these Meta pages when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. | Resource | Use it for | -| -------- | ---------- | -| [Messenger Platform quick start](https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start/) | Meta's own walkthrough of app setup, Page token generation, and the first webhook. | -| [Send API reference](https://developers.facebook.com/docs/messenger-platform/reference/send-api/) | Outbound message types, message tags, and the messaging window rules. | -| [My Apps](https://developers.facebook.com/apps/) | Returning to an app you created, or checking which app owns a Page subscription. | -| [Meta Business Suite](https://business.facebook.com/) | Page settings, Page roles, and business verification. | +|---|---| +| [Messenger Platform quick start](https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start/) | App setup, Page tokens, and the first webhook. | +| [Send API reference](https://developers.facebook.com/docs/messenger-platform/reference/send-api/) | Outbound message types, message tags, and messaging window rules. | +| [My Apps](https://developers.facebook.com/apps/) | Returning to an app or checking which app owns a Page subscription. | +| [Meta Business Suite](https://business.facebook.com/) | Page settings, roles, and business verification. | {{related}} - [Channels](/agent-platform/channels) -- [Set up WhatsApp](/agent-platform/channels/whatsapp) -- [Set up LINE](/agent-platform/channels/line) -- [Set up Telegram](/agent-platform/channels/telegram) \ No newline at end of file +- [Set up Instagram](/agent-platform/channels/instagram) +- [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file diff --git a/agent-platform/channels/ms-teams-copilot.mdx b/agent-platform/channels/ms-teams-copilot.mdx index ca9219040..8a314428b 100644 --- a/agent-platform/channels/ms-teams-copilot.mdx +++ b/agent-platform/channels/ms-teams-copilot.mdx @@ -5,177 +5,274 @@ sidebarTitle: Microsoft Teams [Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Integrate your agent into Microsoft Teams channels, chats, and Microsoft 365 Copilot through an Azure Bot registration and a Teams application. +Connect your agent to Microsoft Teams chats and channels through a single-tenant Azure Bot and a Teams app. You register the bot in Azure, create the Artemis connection, point the bot's messaging endpoint at Artemis, then package and install the Teams app. -## Before you begin +The setup requires: -Complete the following tasks in Microsoft before you create the channel connection in Artemis. You need administrator access to the [Azure Portal](https://portal.azure.com/), the [Microsoft Teams Developer Portal](https://dev.teams.microsoft.com/), and the [Teams Admin Center](https://admin.teams.microsoft.com/). +1. [Prepare the Azure Bot](#prepare-the-azure-bot) and collect its credentials. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its messaging endpoint. +3. [Configure the messaging endpoint](#configure-the-messaging-endpoint) and the Teams channel in Azure. +4. [Create and install the Teams app](#create-and-install-the-teams-app). +5. [Verify the connection](#verify-the-connection) in a real Teams conversation. - - - 1. Sign in to the [Azure Portal](https://portal.azure.com/) and search for **Azure Bot** in Marketplace. - 2. Select **Create** and complete the bot registration. - 3. When the deployment completes, select **Go to resource** under **Next steps**. - +After setup, Teams sends each activity to Artemis. Artemis validates the Bot Framework token, runs the agent, and replies in the same conversation. - - 1. In the Azure Bot resource, go to **Settings** -> **Configuration**. - 2. Select the **Manage password** link beside the **Microsoft App ID**. This opens the app registration's **Certificates & secrets** page. - 3. Select **+ New client secret** and create the secret. - 4. Copy the secret value immediately and store it securely. - 5. Go to the app registration's **Overview** page and copy the **Application (client) ID**. This is your Microsoft App ID, also called the Enterprise App ID later in this article. - 6. Copy the **Directory (tenant) ID** from the same page. +**Important considerations** - When you copy the client secret, use the **Value**, not the **Secret ID**. The Secret ID won't authenticate. The Value appears only once. If you navigate away before copying it, create a new client secret. - +- **Use the same Microsoft App ID everywhere**: The **Bot App ID**, the **App ID** credential, the Azure Bot Microsoft App ID, and the Teams manifest `botId` must all be the same GUID. Artemis selects the connection by that ID and checks that the Bot Framework JWT audience matches it. +- **Use a single-tenant bot**: Microsoft ended support for creating new multi-tenant Azure Bot registrations after July 31, 2025. Existing multi-tenant bots keep running, but this setup uses a single-tenant identity and the exact App Tenant ID. +- **The client secret Value appears once**: Copy the **Value**, not the **Secret ID**. The Secret ID can't authenticate. +- **Manifest changes need a reinstall**: Endpoint and runtime changes apply immediately. Scope, `supportsFiles`, icon, and command changes need an updated package and a reinstall. - - 1. In the app registration, go to **Authentication (Preview)** -> **Supported accounts**. - 2. Select **Multiple Entra ID tenants**, choose **Allow all tenants**, and save. - +## Prerequisites - - 1. Return to the Azure Bot resource and go to **Settings** -> **Channels**. - 2. Enable **Microsoft Teams** and **Microsoft 365**. - +Confirm these before you start. + +- Access to the Microsoft Entra tenant where you'll install the Teams app, with permission to manage app registrations and Azure Bot resources. +- A Teams policy that permits custom app upload, or an administrator who can publish the app. +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. + +--- - - 1. Sign in to the [Microsoft Teams Developer Portal](https://dev.teams.microsoft.com/). - 2. Create a new application or import an existing manifest. - 3. Go to **Configure** -> **Basic information**, enter the **Short name** and **Long name**, and set the **Application (client) ID** to the Microsoft App ID you copied in step 2. +## Prepare the Azure Bot + +Do this in Azure before you open Artemis. Select **Open Azure portal** in the setup guide to jump straight there. + + + + In the [Azure portal](https://portal.azure.com/), create an Azure Bot or open the existing one dedicated to this agent. Keep development and production on separate bot registrations. - - 1. Go to **Configure** -> **App features** and select **Bot**. - 2. Enter the Enterprise App ID as the bot ID. - 3. Add the project commands, utterances, and descriptions. - 4. Select the **Personal**, **Team**, and **Group Chat** scopes. + + For a new bot, choose **Single Tenant**, and create or select the Microsoft Entra app registration that represents the bot. Artemis uses an App ID, client secret, and tenant ID, so don't select a managed-identity-only setup. - - 1. Go to **App package editor** -> **Actions** -> **Edit** to open `manifest.json`. - 2. Update the Web App ID (`webApplicationInfo.id`) and the Copilot/Agents ID (`copilotAgents.customEngineAgents.id`) to the Enterprise App ID in both locations. - 3. To support file attachments, set `bots[0].supportsFiles` to `true`. - 4. Select **Update** and confirm. + + 1. Go to **Azure Bot** -> **Configuration**. + 2. Copy the **Microsoft App ID**, a GUID. + 3. Copy the **App Tenant ID**, the Microsoft Entra Directory (tenant) ID. - Attachment ingestion currently supports personal chat scope only. + Don't copy the Teams app package ID, the Azure resource ID, an object ID, or a value beginning with `28:`. - - 1. In the Teams Developer Portal, go to **Publish** -> **Publish to org**, select **Get started**, and publish the application. - 2. Open the [Teams Admin Center](https://admin.teams.microsoft.com/) and go to **Teams apps** -> **Manage apps**. - 3. Search for the application, open it, and publish it. + + 1. Select **Manage** beside **Microsoft App ID** to open the linked app registration. + 2. Go to **Certificates & secrets** and create a client secret with an approved expiration. + 3. Copy the **Value** immediately and store it in your secret manager. -## Create the channel connection in Artemis +--- + +## Artemis channel configuration + +Create the connection before Teams sends an activity. Artemis needs the saved App ID and credentials to resolve the URL, validate inbound JWTs, get Bot Framework tokens, and send replies. + +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Microsoft Teams** -> **+ New**. The **New Microsoft Teams Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see. Name it for the Teams app and environment. | + | **Bot App ID** | **Azure Bot** -> **Configuration** -> **Microsoft App ID** | The routing identifier in the messaging endpoint URL. | + | **App ID** | The same Microsoft App ID | The encrypted credential for Bot Framework calls. | + | **Client Secret** | The client secret **Value** | Authorizes outbound Bot Framework calls and member lookup. | + | **Azure Tenant ID** | **Azure Bot** -> **Configuration** -> **App Tenant ID** | The tenant for the client-credentials token request. | + | **Environment** | Your published environments | The environment whose active deployment answers Teams. Leave the working copy default only while you develop. | + | **Initial Status** | Defaults to **Active** | Keep it **Active**. | + + Artemis asks for the Microsoft App ID twice, once as the routing identifier and once as an encrypted credential. Paste the same GUID into both fields. + +4. Select **Create**. +5. Copy the **Webhook URL** from the connection's summary panel. It ends with the encoded Microsoft App ID. + +--- + +## Configure the messaging endpoint + +Point the Azure Bot at Artemis and turn on the Teams channel. + +1. Confirm the Artemis connection is **Active**, and that **Bot App ID** and **App ID** match. +2. In **Azure Bot** -> **Configuration**, paste the full Artemis URL into **Messaging endpoint**. Turn on **Enable Streaming Endpoint**, and select **Apply**. +3. Reopen **Configuration** and confirm Azure kept the complete endpoint. +4. In the Azure Bot resource, open **Channels**, add **Microsoft Teams**, accept the terms, and save. The bot receives no Teams activity until you configure this channel. + +Use the full URL that ends with the Microsoft App ID. Don't replace it with the generic endpoint, the Teams app package ID, a tenant ID, an object ID, or the Azure resource name. + +A successful save doesn't prove authentication. Continue through installation and a real message test. + +--- + +## Create and install the Teams app + +Package the bot as a Teams app. Select **Open Teams Developer Portal** in the setup guide to jump straight there. - - Open Artemis, select the required project, and go to **Deployments** -> **Channels** -> **MESSAGING** -> **Microsoft Teams** -> **+ New**. On the **New Microsoft Teams Connection** dialog, provide the following fields. + + In the [Teams Developer Portal](https://dev.teams.microsoft.com/), create an app for this bot, and add the name, descriptions, icons, developer details, and privacy and terms URLs your organization requires. + - | Field | Description | - | ----- | ----------- | - | **Display Name** | A label for the connection, for example `Microsoft Teams Production`. Up to 255 characters. | - | **Bot App ID** | The Microsoft App ID of the bot configured in your Teams application. Up to 255 characters. | - | **App ID** | The Microsoft App ID from the Azure Bot registration, also called the Enterprise App ID. | - | **Client Secret** | The client secret value you created in the Azure app registration. | - | **Azure Tenant ID** | The Directory (tenant) ID from the app registration's Overview page in the Azure Portal. | - | **Environment** | Select an environment to follow its active deployment. If no environment has an active deployment yet, leave the default to use the working copy and bind the connection later from the **Deployment** tab. | - | **Initial Status** | **Active** connections can be used immediately. **Inactive** connections stay saved but disabled until you activate them. Set this to **Active**. | - - **Bot App ID** and **App ID** both take a Microsoft App ID. The app ID of your Teams app must match the app ID in the Azure Bot registration and the values you enter here. A mismatch is the most common cause of a Teams integration that won't connect. - - Select **Create**. + + 1. Under **App features**, add **Bot**, select **Enter a bot ID**, and paste the Microsoft App ID. + 2. Enable only the scopes you'll test and support: `personal`, `team`, and `groupChat`. Each is a separate install context. + + + + Set `supportsFiles` to `true` when users send attachments. Artemis ingests file and inline-image attachments only from personal chats, and skips file-only activities in teams and group chats. + + ```json + { + "bots": [ + { + "botId": "", + "scopes": ["personal", "team", "groupChat"], + "supportsFiles": true, + "isNotificationOnly": false + } + ] + } + ``` + + For Microsoft 365 Copilot, also set `webApplicationInfo.id` and `copilotAgents.customEngineAgents.id` to the Microsoft App ID. - - 1. Open the connection you created and copy the **Webhook URL** from the **Overview** tab. - 2. In the [Azure Portal](https://portal.azure.com/), open the Azure Bot resource and go to **Configuration**. - 3. Paste the Webhook URL into the **Messaging endpoint** field. - 4. Enable the **Streaming Endpoint** and select **Apply**. + + Resolve every Developer Portal validation error, then download the app package. If you edit the manifest directly, keep `botId` equal to the Microsoft App ID and include valid color and outline icons. - - 1. Open [Teams](https://teams.cloud.microsoft/) and go to **Apps**. - 2. Search for the published application, open it, and select **Add**. To test in Copilot, select **Open with Copilot**. - 3. Trigger the configured queries and verify the Artemis response. + + For development, go to **Apps** -> **Manage your apps** -> **Upload a custom app**, if tenant policy allows it. For a controlled rollout, have a Teams administrator publish the app and assign app permission and setup policies. -## Key values reference +--- -| Value | Where it comes from | Where it's used | -| ----- | ------------------- | --------------- | -| **Microsoft App ID (Enterprise App ID)** | The Azure Bot registration's Application (client) ID | The **Bot App ID** and **App ID** fields in Artemis, the bot ID in the Teams application, and the app package IDs in the Teams Developer Portal | -| **Client Secret** | Created under **Certificates & secrets**; copy the value immediately after creation | The **Client Secret** field in Artemis | -| **Azure Tenant ID** | The Directory (tenant) ID in the Azure Portal (admin account) | The **Azure Tenant ID** field in Artemis | -| **Webhook URL** | The Artemis Microsoft Teams connection's **Overview** tab | The Azure Bot **Messaging endpoint** | +## Verify the connection -## Manage the channel connection +Artemis doesn't synthesize Teams activities, so a real conversation is the only end-to-end proof. -Opening a channel from **Deployments** -> **Channels** -> **MESSAGING** -> **Microsoft Teams** shows four tabs: **Overview**, **Credentials**, **Configuration**, and **Deployment**. +1. Install the app for yourself, open its personal chat, and send a unique message. +2. Confirm a typing indicator where applicable, and one reply from this bot rather than an older installation or another environment. +3. If the agent renders actions or forms, submit an Adaptive Card `Action.Execute`, and confirm the values reach the same session. +4. Install the bot in a test team and group chat only if the manifest includes those scopes. Confirm @mentions and routing in each context, because a personal-chat pass doesn't prove team or group behavior. +5. With `supportsFiles` on, send an approved file and an inline image in personal chat, and confirm the agent processes them. +6. To test in Copilot, open the app in Teams and select **Open with Copilot**. - - - The **Connection Summary** shows these fields. +| Capability | Where it works | +|---|---| +| `text`, typing, streaming | Every enabled scope | +| Adaptive Cards with `Action.Execute` | Every enabled scope | +| File and inline-image attachments | Personal chat only | - | Field | Description | - |-----------------|-----------------------------------| - | **Status** | For example: *Active* | - | **Created** | Timestamp the channel was created | - | **Updated** | Timestamp of the last change | - | **Environment** | For example: `staging` | - | **Source Type** | `Channel Connection` | - | **Source ID** | Unique channel identifier (UUID) | +--- - Under **Setup Instructions**, the tab shows the **Webhook URL** to set as the bot's messaging endpoint in Azure, the **Bot App ID** for reference, and the **Require verified Teams identity** toggle. +## Security and identity boundaries - #### Require verified Teams identity +Inbound traffic and outbound replies each have their own protection. - Turn this on to require Microsoft-resolved Teams profile identity before the connection starts or resumes a session. Leave it off for baseline Teams conversations. +- **Inbound JWT**: Every activity must carry a Microsoft Bot Framework bearer JWT. Artemis validates the signing key, issuer, App ID audience, and the service URL claim when present. +- **Client secret**: It authorizes outbound Bot Framework calls and member lookup. Store it only in Artemis, never in the manifest, browser code, screenshots, or tickets. +- **Secret rotation**: Client secrets expire. Create a replacement before expiration, update Artemis, verify a reply, and only then remove the old secret. +- **Reply targets**: Artemis replies only to the `serviceUrl` from the authenticated activity, and checks allowed attachment hosts before it forwards a bot token. +- **Environments**: Use separate App IDs, secrets, Azure Bot resources, Teams app packages, and connections for development and production. - When the toggle is on, Runtime resolves the sender's Microsoft profile email or UPN through the Bot Connector member endpoint before it allows the turn. If the identity can't be resolved, the turn doesn't proceed. This confirms that the person on the other end is the Teams user their profile claims they are, which matters for agents that act on a user's behalf or return information scoped to that user. +--- + +## Manage the channel connection - The toggle relies on the credentials already configured for this connection or its selected auth profile, and on the bot staying installed and reachable in Teams. It doesn't use Microsoft Graph consent, OBO settings, or Graph scopes. +Open a connection from **Deployments** -> **Channels** -> **Microsoft Teams** to manage it. The page has a header, three tabs, and a summary panel on the right. - The **Stronger identity verification setup** panel below the toggle lists the specific requirements to complete when you enable it. - +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Microsoft Teams** and **Channel Connection**. | +| **Identifier** | The Microsoft App ID this connection routes on. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The messaging endpoint for Azure, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + + - Credentials are saved and encrypted after creation; the fields show placeholder text and accept new values only if you want to update them. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. - | Field | Description | - |----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| - | **Use Auth Profile** | Toggle on to authenticate through a saved Auth Profile instead of entering credentials manually. When enabled, select the profile from the dropdown in place of the fields below. | - | **App ID** | Your Microsoft App ID. Shown as *(saved — enter to update)*; leave blank to keep the current value. | - | **Client Secret** | The client secret from your Azure Bot registration. Shown as *(saved — enter to update)*; leave blank to keep the current value. | - | **Azure Tenant ID** | The Directory (tenant) ID from the Azure Overview page. Shown as *(saved — enter to update)*; leave blank to keep the current value. | + | Field | Description | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **App ID** | The Microsoft App ID credential. | + | **Client Secret** | Replace it here when you rotate the secret in Azure. | + | **Azure Tenant ID** | The App Tenant ID. | - Select **Save Credentials** to apply any changes. + Select **Save Credentials** to apply your changes. - Under **General**, update the **Display Name**. + Update how the connection behaves. **Microsoft Teams Settings** holds the provider-specific fields. + + | Setting | Description | + |---|---| + | **Bot App ID** | Read-only, with a copy control. To serve another bot, create a new connection. | + | **Enable Streaming** | Under **Response Streaming**. Streams responses to Teams as the agent generates them. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Require verified Teams identity** | Under **Stronger identity verification**. Requires a Microsoft-resolved Teams profile identity before the connection starts or resumes a session. Leave it off for baseline Teams conversations. | + | **Webhook URL** | The messaging endpoint, with a copy control. | - Under **Microsoft Teams Settings**, configure the following. + When you turn on **Require verified Teams identity**: - | Field | Description | - |----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| - | **Bot App ID** | The Microsoft App ID of the bot, shown for reference. You can't change it after creation. | - | **Enable Streaming** | Under **Response Streaming**, turn this on to stream LLM responses to Teams as the agent generates them, instead of waiting for the full response. Turn it off to deliver each response as a single message. | + - Artemis calls the Bot Connector member endpoint, `/v3/conversations/{conversationId}/members/{userId}`, to resolve the sender's profile email or UPN before it allows the turn. + - It uses the `app_id`, `client_secret`, and `tenant_id` on this connection or its auth profile. + - The bot must stay installed and reachable, with the Azure Bot **Messaging endpoint** pointing at this connection. + - It doesn't use Microsoft Graph consent, OBO settings, or `https://graph.microsoft.com/.default` scopes. - Select **Save Changes** to apply any changes. + Select **Save Changes** to apply your changes. - The **Deployment** tab shows these fields. + Choose which deployed version answers Teams. - | Field | Description | - |-----------------------|---------------------------------------------------------------------------------------------------------------------| - | **Agent Version** | An **Environment** dropdown (for example: `Staging`) that selects which deployed version handles incoming messages. | - | **Active Deployment** | Shows the bound deployment version and when it was deployed. | + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Select **Save Changes** after switching the environment or version. + Select **Save Changes** after you switch the environment. - \ No newline at end of file + + +--- + +## Troubleshoot connection issues + +Most failures trace to a mismatched App ID or a stale manifest. + +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Connection not found or `404` | Wrong endpoint or identifier | Confirm the endpoint ends with the exact Microsoft App ID, and that the **Bot App ID** has no `28:` prefix. | +| `401` or JWT validation failure | App ID mismatch | Confirm the App ID matches the token audience, the Azure Bot and Teams app reference the same registration, and requests reach Artemis unchanged over HTTPS. | +| Inbound message arrives but no reply | Outbound credential or deployment issue | Confirm the client secret Value is current, the **Azure Tenant ID** is correct, the environment has a runnable deployment, and your network allows outbound token requests. | +| Teams won't install the app | Validation or policy block | Resolve Developer Portal validation errors, confirm tenant policy allows custom app upload, or ask a Teams administrator to publish and permit the app. | +| Personal chat works but team or group chat doesn't | Scope missing or not reinstalled | Add the scope to the manifest, reinstall the updated package, add the app to the target context, and test the required @mention behavior. | +| Text works but files don't | Files not enabled or outside policy | Set `supportsFiles` to `true`, reinstall, test in personal chat, stay within the size limit, and confirm Artemis trusts the download host. | +| Adaptive Card buttons don't submit | Unsupported card or stale app | Use a supported Adaptive Card with `Action.Execute`, confirm the app is current, and check whether the invoke activity reaches the same connection. | + +--- + +## Microsoft reference + +Use these pages when you need detail beyond what this article covers. Artemis field names and the runtime endpoint shown in the connection stay the source of truth for this integration. + +| Resource | Use it for | +|---|---| +| [Connect a bot to Teams](https://learn.microsoft.com/azure/bot-service/channel-connect-teams) | Adding the Microsoft Teams channel to an Azure Bot. | +| [Upload a custom Teams app](https://learn.microsoft.com/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) | Sideloading the app package for testing. | +| [Teams Developer Portal](https://dev.teams.microsoft.com/) | Creating, validating, and downloading the app package. | +| [Teams Admin Center](https://admin.teams.microsoft.com/) | Publishing the app and assigning policies. | + +{{related}} + +- [Channels](/agent-platform/channels) +- [Set up Slack](/agent-platform/channels/slack) +- [Set up AI for Work](/agent-platform/channels/ai-for-work) \ No newline at end of file diff --git a/agent-platform/channels/slack.mdx b/agent-platform/channels/slack.mdx index 2449f8bf2..a48023bf9 100644 --- a/agent-platform/channels/slack.mdx +++ b/agent-platform/channels/slack.mdx @@ -5,183 +5,287 @@ sidebarTitle: Slack [Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Deploy your agent as a Slack bot for team collaboration. Connect your Slack app to Artemis by entering its credentials manually. +Deploy your agent as a Slack bot so your team reaches it through direct messages and channel mentions. You connect your own Slack app to Artemis, either by entering its credentials manually or through **Add to Slack**. - - **Redirect URL and Request URL are different.** Slack uses two URLs at different stages: +The setup requires: - * **OAuth Redirect URL** — used only during the **Add to Slack** authorization flow, registered under **OAuth & Permissions** so Slack can return authorization back to Studio. - * **Events Request URL** — generated for this connection and pasted under **Event Subscriptions → Request URL** in Slack, allowing Slack to deliver messages and events to Studio. - +1. [Choose a setup method](#choose-a-setup-method). +2. [Prepare your Slack app](#prepare-your-slack-app) with the scopes the agent needs. +3. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +4. [Event subscriptions in Slack](#event-subscriptions-in-slack): register the Webhook URL so Slack delivers messages. +5. [Verify the connection](#verify-the-connection) in a direct message and in a channel. -## Create an app in Slack +After you complete the configuration, Slack posts each direct message and @mention to Artemis, and the agent replies in the same conversation. + +**Important considerations** + +- **Manual credentials are the recommended setup**: They connect your own Slack app without depending on platform-managed OAuth. **Add to Slack** works only when your platform administrator enables it. +- **Slack uses two different URLs**: The OAuth Redirect URL serves only **Add to Slack**. The Events Request URL delivers messages. Pasting one in place of the other breaks the setup. +- **Create the connection before you register events**: Slack verifies the Request URL the moment you paste it, so Artemis must already hold the matching Team ID:App ID and Signing Secret. +- **Treat the Bot Token and Signing Secret as production secrets**: Paste them only into Artemis. Keep them out of tickets, chat messages, screenshots, and source control. + +## Prerequisites + +Confirm these before you start, because Slack app changes need workspace permissions. + +- Permission to create or manage Slack apps in the target workspace, or a Workspace Owner or App Manager who approves the app. +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. + +--- + +## Choose a setup method + +Both methods produce the same connection. They differ in how Artemis gets the Slack credentials. + + + + Recommended. You copy the Team ID, App ID, Bot Token, and Signing Secret from your Slack app. + + + Slack authorizes the workspace and fills in the identifiers. Requires administrator enablement. + + + +### Slack URLs at a glance + +Slack asks for URLs on several screens. Each URL has one job. + +| URL | Purpose | Where it goes in Slack | +|---|---|---| +| **OAuth Redirect URL** | Returns **Add to Slack** authorization to Artemis. Manual setup doesn't use it. | **OAuth & Permissions** -> **Redirect URLs** | +| **Webhook URL** (Events Request URL) | Delivers messages and events for this connection | **Event Subscriptions** -> **Request URL**, and **Interactivity & Shortcuts** -> **Request URL** | +| **Slash Command URL** | Delivers slash commands for this connection | The command's **Request URL** | + +--- + +## Prepare your Slack app + +Set up the app in Slack before you open Artemis. Select **Open Slack app settings** in the setup guide to jump straight to your apps. - At [api.slack.com/apps](https://api.slack.com/apps), select **Create New App**, choose **From scratch**, name the app, and choose a development workspace. + 1. Go to [Your Apps](https://api.slack.com/apps) and select **Create New App**. + 2. Choose **From scratch**, name the app, and choose a development workspace. - - You need three values from Slack before you can create the connection in Artemis: + + Skip this step for manual setup. + + 1. Go to **OAuth & Permissions** -> **Redirect URLs**. + 2. Add the OAuth Redirect URL that the Artemis setup guide shows, and save. - | Value | Where to find it | - | --- | --- | - | **Team ID** | Open your workspace in a browser. In `https://app.slack.com/client/T.../...` the segment beginning with `T` is your Team ID. | - | **App ID** | Go to **Basic Information** -> **App Credentials** and copy **App ID**. | - | **Signing Secret** | On the same **App Credentials** panel, select **Show** next to **Signing Secret** and copy it. | + Slack requires an exact match on scheme, host, port, path, and trailing slash. - Go to **OAuth & Permissions** and, under **Bot Token Scopes**, add: - - | Scope | Purpose | - | --- | --- | - | `chat:write` | Send messages as the bot. | - | `im:history` | Read direct message history with the bot. | - | `commands` | Required for slash commands. | - | `app_mentions:read` (optional)| Read @mentions of the bot in channels. | - | `files:read` (optional)| Required for file attachments. | - | `chat:write.public` (optional)| Required to post to public channels the bot hasn't joined. | - | `users:read` (optional)| Required for tools that look up the message sender. See [Sessions and sender identity](#sessions-and-sender-identity). | + Go to **OAuth & Permissions** -> **Bot Token Scopes** and add the core scopes. Add optional scopes only for the feature that needs them. + + | Scope | Required for | + |---|---| + | `chat:write`, `app_mentions:read`, `im:history`, `im:read`, `im:write` | Core messaging. Always add these. | + | `files:read` | File attachments | + | `commands` | Slash commands | + | `chat:write.public` | Posting to public channels the bot hasn't joined | + | `users:read` | Tools that look up the sender's profile | + | `users:read`, `users:read.email` | **Require verified Slack identity** | - - On the same **OAuth & Permissions** page, select **Install to Workspace** (or **Reinstall to Workspace** if the app is already installed). Once installed, copy the **Bot User OAuth Token** from **OAuth Tokens** — it begins with `xoxb-`. - - Reinstall the app whenever you add or change scopes so the bot token receives the new grants. + + 1. Select **Install to Workspace** and approve the permissions. + 2. Reinstall the app whenever you change scopes, so the bot token receives the new grants. -## Integrate the Slack app in Artemis +--- - - - Open Artemis, select the required project, and go to **Deployments** -> **Channels** -> **MESSAGING** -> **Slack** -> **+ New**. - +## Artemis channel configuration - - Select **Enter credentials manually instead**, then fill in the following fields. +Create the connection before you register event subscriptions. Slack sends its verification challenge immediately, and only a saved connection can answer it. - | Field | Description | - | --- | --- | - | **Display Name** | A label for the connection, for example `Slack Production`. Up to 255 characters. | - | **Slack Team ID:App ID** | The Team ID and App ID from Slack, joined by one colon with no spaces, for example `T0xxxxxxxxx:A0xxxxxxxxx`. | - | **Bot Token** | The Bot User OAuth Token from **OAuth & Permissions** -> **OAuth Tokens**. Must begin with `xoxb-`. | - | **Signing Secret** | The signing secret from **Basic Information** -> **App Credentials**. | - | **Environment** | Select an environment to follow its active deployment. | - | **Provider Verification Strength** | **Weak (default)** is set by default. Choose **Strong** only for channels/providers whose identity assertions you trust for stronger continuity and linking decisions. | - | **Initial Status** | **Active** connections can be used immediately. **Inactive** connections stay saved but disabled until you activate them. | - - Select **Create**. - +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Slack** -> **+ New**. The **New Slack Connection** dialog opens, with the setup guide on the left and the connection fields on the right. +3. Complete the steps for your setup method: - - Open the connection you created and copy the **Webhook URL** from the **Overview** tab. Go back to your Slack app's **Event Subscriptions** page, turn **Enable Events** on, and paste the Webhook URL into **Request URL**. Wait for Slack to show **Verified**, then, under **Subscribe to bot events**, add: + + + 1. Select **Enter credentials manually instead**. + 2. Collect the values below from Slack and enter them. - | Event | Description | - | --- | --- | - | `message.im` | Direct messages sent to the bot. | - | `app_mention` | @mentions in channels where the app is invited. | + | Artemis field | Where to find it in Slack | Notes | + |---|---|---| + | **Slack Team ID:App ID** | Team ID: open the workspace in a browser and read the segment beginning with `T` in the `app.slack.com/client/` URL. App ID: **Basic Information** -> **App Credentials**. | Join the two values with one colon and no spaces. The Team ID doesn't appear in the Slack app settings URL. | + | **Bot Token** | **OAuth & Permissions** -> **OAuth Tokens** -> **Bot User OAuth Token** | Begins with `xoxb-`. Authorizes every reply the agent sends. | + | **Signing Secret** | **Basic Information** -> **App Credentials** -> **Signing Secret** | Verifies that each inbound request comes from Slack. | + - Save your changes. - + + 1. Enter a **Display Name** that identifies the workspace and environment. + 2. Select **Add to Slack**, choose the intended workspace, review the requested permissions, and select **Allow**. + 3. Confirm the connected workspace. Slack fills in the **Slack Team ID:App ID** for you. - - Send the app a direct message, then invite it to a channel and @mention it. Confirm the agent replies in both places. - - + If Slack reports that the app needs approval, ask a Workspace Owner or App Manager to approve it, then select **Add to Slack** again. + + -## Manage the channel connection +4. Configure the remaining fields: -Opening a channel from **Deployments** -> **Channels** -> **MESSAGING** -> **Slack** shows four tabs: **Overview**, **Credentials**, **Configuration**, and **Deployment**. + | Artemis field | What it controls | + |---|---| + | **Display Name** | The label operators see in the connections list. Routing ignores it. | + | **Environment** | The environment whose active deployment answers messages. If no environment has an active deployment, leave the default to use the working copy, and bind it later from the **Deployment** tab. | + | **Provider Verification Strength** | How far the runtime trusts Slack's identity assertion when it links a sender to an existing session. Keep **Weak** unless you base continuity and account-linking decisions on Slack identity. | + | **Initial Status** | **Active** takes traffic immediately. **Inactive** saves the connection disabled until you activate it. | - - - The **Connection Summary** shows these fields. +5. Select **Create**. +6. Open the connection and copy the **Webhook URL** from the summary panel on the right. The URL ends with this connection's encoded Team ID:App ID, so copy it rather than building it. - | Field | Description | - | --------------- | --------------------------------- | - | **Status** | For example: *Active* | - | **Created** | Timestamp the channel was created | - | **Updated** | Timestamp of the last change | - | **Environment** | For example: `staging` | - | **Source Type** | `Channel Connection` | - | **Source ID** | Unique channel identifier (UUID) | +--- - Under **Setup Instructions**: +## Event subscriptions in Slack - * **Require verified Slack identity** - Toggle on to require Slack workspace user identity with a resolvable email before this connection starts or resumes a session. Guests, external Slack Connect users, and users without email remain blocked. +Event subscriptions turn the app into a conversation. Until Slack has the Request URL, the agent never receives a message. - Before enabling this policy, complete the **Verified Slack identity setup**. Runtime uses Slack's `users.info` to resolve the sender's workspace email. +1. Confirm the Artemis connection exists and is **Active**. +2. In your Slack app, go to **Event Subscriptions** and turn on **Enable Events**. +3. Paste the connection's **Webhook URL** into **Request URL**, and wait for Slack to show **Verified**. +4. Under **Subscribe to bot events**, add `message.im` and `app_mention`. +5. Select **Save Changes**, then reinstall the app if Slack prompts you. - 1. In the Slack app's **OAuth & Permissions**, add these Bot Token Scopes: `users:read` and `users:read.email`. - 2. Reinstall or re-authorize the Slack app after adding scopes so the bot token receives the new permissions. +If Slack reports that the challenge value wasn't returned, check that the URL ends with the encoded Team ID:App ID, that the connection exists and is **Active**, and that its Signing Secret matches this Slack app. Don't use the generic `/slack/webhook` URL for verification. - * The tab also shows the **Webhook URL** to paste into Slack's Event Subscriptions **Request URL**, and the **Slack Team ID:App ID** for reference. Select the copy icon next to either value to copy it. - +### Validation checklist - - Credentials are saved and encrypted after creation; the fields show placeholder text and accept new values only if you want to update them. +Work down this list once per connection. - | Field | Description | - | --- | --- | - | **Use Auth Profile** | Toggle on to authenticate through a saved Auth Profile instead of entering credentials manually. When enabled, select the profile from the dropdown in place of the fields below. | - | **Bot Token** | The Bot User OAuth Token from Slack's **OAuth & Permissions** -> **OAuth Tokens**. Shown as *(saved — enter to update)*; leave blank to keep the current value. | - | **Signing Secret** | The signing secret from Slack's **Basic Information** -> **App Credentials**. Shown as *(saved — enter to update)*; leave blank to keep the current value. | +| Validation item | Expected result | +|:---|:---| +| Prepare the Slack app | Core scopes added and the app installed in the workspace. | +| Create the Artemis connection | Saved as **Active** with the right Team ID:App ID and environment. | +| Register events | **Request URL** shows **Verified**, and `message.im` and `app_mention` appear under bot events. | +| Test both paths | The agent replies once in a direct message and once to an @mention. | - Select **Save Credentials** to apply any changes. - +## Verify the connection - - Under **General**, update the **Display Name** and **Provider Verification Strength**. +Slack has two conversation paths, and each needs its own test. - Under **Slack Settings**, the following fields apply. +1. Send the app a direct message and confirm the agent replies. +2. Invite the app to a channel, @mention it, and confirm the agent replies in the thread. +3. If no reply arrives, open **Sessions** and search for your message. A session means Slack reached Artemis and the reply failed. No session means the event never arrived. - | Field | Description | - | --- | --- | - | **Slack Team ID:App ID** | The Team ID and App ID entered at creation, shown for reference. You can't change it after creation. | +--- - Under **Response Streaming**, configure the following. +## Optional Slack features - | Field | Description | - | --- | --- | - | **Enable Streaming** | Stream LLM responses to Slack in real time instead of waiting for the full response. | - | **Chunk Size (characters)** | Minimum characters to buffer before sending to Slack. Lower values feel faster but make more API calls. | +Turn these on only when your agent uses them. Each one reuses a connection-specific URL. + +| Feature | Setup in Slack | +|---|---| +| **Buttons, menus, and shortcuts** | Turn on **Interactivity & Shortcuts** and paste the same Webhook URL into its **Request URL**. | +| **Slash commands** | Add the `commands` scope, reinstall the app, create the command, and paste the connection's Slash Command URL into its **Request URL**. | +| **Verified Slack identity** | Add `users:read` and `users:read.email`, reinstall the app, then turn on **Require verified Slack identity** in the **Configuration** tab. | + +--- + +## Sessions and sender identity + +The Slack channel scopes each conversation to a thread and tells the agent who sent each message. + +| Behavior | Description | +|---|---| +| One session per thread | Each Slack thread runs as its own session, so separate requests in the same channel never share context. | +| Sender user ID | The runtime adds the sender's Slack user ID to `session._metadata` as `slackUserId`. A tool can pass it to Slack's [users.info](https://api.slack.com/methods/users.info) method, which needs the `users:read` scope. | + +--- + +## Manage the channel connection + +Open a Slack connection from **Deployments** -> **Channels** -> **Slack** to manage it. The page has a header, three tabs, and a summary panel on the right. + +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - Under **Authorization Message**, configure the message shown when a tool needs the user to authorize. +**Summary panel.** Stays visible on every tab and carries the values Slack needs. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Slack** and **Channel Connection**. | +| **Identifier** | The Slack Team ID:App ID this connection routes on. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The Request URL for **Event Subscriptions** and **Interactivity & Shortcuts**, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + + + + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | --- | --- | - | **Message template** | The message text, with insertable variables: `{{#authorizations}}`, `{{profileName}}`, `{{authLink}}`, and `{{remaining}}`. Select **See all variables** for the full list, or **Show preview** to preview the rendered message. | + |---|---| + | **Use Auth Profile** | Authenticates through a saved auth profile in place of the fields below. | + | **Bot Token** | Authorizes outbound replies. Replace it here after you reinstall or rotate the app. | + | **Signing Secret** | Verifies inbound requests. A mismatch fails Slack's verification challenge. | - Select **Save Changes** to apply any changes. + Select **Save Credentials** to apply your changes. + + + + Update the connection's behavior in Slack. + + | Setting | Description | + |---|---| + | **Display Name** | The label operators see in the connections list. | + | **Provider Verification Strength** | How far the runtime trusts Slack's identity assertion. | + | **Slack Team ID:App ID** | Read-only. A connection pointed at the wrong app needs replacing rather than editing. | + | **Require verified Slack identity** | Requires a workspace user with a resolvable email before the connection starts or resumes a session. Guests, external Slack Connect users, and users without email stay blocked. The runtime resolves the email through `users.info`, so add `users:read` and `users:read.email` and reinstall the app first. | + | **Enable Streaming** | Streams responses to Slack as the agent generates them. | + | **Chunk Size (characters)** | The minimum characters Artemis buffers before each update. Lower values feel faster and make more Slack API calls. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **See all variables** for the full list, and select **Show preview** to check it. | + + Select **Save Changes** to apply your changes. - The **Deployment** tab shows these fields. + Choose which deployed version answers the channel. - | Field | Description | - | --- | --- | - | **Agent Version** | An **Environment** dropdown (for example: `Staging`) that selects which deployed version handles incoming messages. | - | **Active Deployment** | Shows the bound deployment version and when it was deployed. | + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. Check it when the agent behaves like an older build. | - Select **Save Changes** after switching the environment or version. + Select **Save Changes** after you switch the environment. -## Sessions and sender identity +--- -The Slack channel scopes each conversation to a thread and tells your agent who sent each message. Both behaviors matter when you design agents for busy channels or build tools that act on behalf of a specific user. +## Troubleshoot connection issues -| Behavior | Description | -| --- | --- | -| One session per thread | Each thread in a Slack channel runs as its own session. Separate requests posted in the same channel don't share conversation state, so context from one request never leaks into another. | -| Sender user ID | The runtime adds the sender's Slack user ID to the session as `slackUserId` in `session._metadata`. Agent tools can read it to identify the person who sent the message. | +Start with the **Sessions** check from [Verify the connection](#verify-the-connection), then match the symptom here. -To look up the sender's profile, pass `slackUserId` to Slack's [users.info](https://api.slack.com/methods/users.info) method from a tool. The method needs the `users:read` bot token scope, so add it under **OAuth & Permissions** and reinstall the app before you rely on the lookup. +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Slack's challenge verification fails | The connection doesn't exist yet, the URL is wrong, or the Signing Secret doesn't match | Create the connection first, copy the Webhook URL from the connection's summary panel, and confirm the Signing Secret comes from the same Slack app. | +| **Add to Slack** fails before the Slack window opens | Artemis can't start the OAuth flow | Ask your platform administrator to confirm Artemis allows the request origin and the Slack app holds the exact OAuth Redirect URL. | +| Slack reports that the app needs approval | Your workspace restricts app installs | Ask a Workspace Owner or App Manager to approve the app, then run **Add to Slack** again. | +| You can't find the Team ID | You looked in the Slack app settings URL | Read the `T` segment from the workspace's `app.slack.com/client/` browser URL. The `api.slack.com/apps/` URL shows only the App ID. | +| The bot receives events but doesn't reply | Missing scope, inactive connection, or the bot isn't in the channel | Confirm the installed app has `chat:write`, the connection is **Active**, and someone invited the app to the channel. | +| Behavior doesn't change after you edit scopes or events | Slack hasn't applied the change | Save the Slack configuration and reinstall the app before you test again. | +| Users get blocked from starting a session | **Require verified Slack identity** is on | Confirm the user is a workspace member with an email, and that the app holds `users:read` and `users:read.email`. | -## Optional Slack features +--- + +## Slack reference + +Use these pages when you need detail beyond what this article covers. + +| Resource | Use it for | +|---|---| +| [Your Apps](https://api.slack.com/apps) | Creating an app or returning to its settings. | +| [Using HTTP Request URLs](https://docs.slack.dev/apis/events-api/using-http-request-urls/) | How Slack delivers events to a Request URL. | +| [URL verification](https://docs.slack.dev/reference/events/url_verification) | The challenge Slack sends when you register a Request URL. | +| [Verifying requests from Slack](https://api.slack.com/authentication/verifying-requests-from-slack) | How the Signing Secret proves a request came from Slack. | +| [Scopes](https://api.slack.com/scopes) | What each bot token scope grants. | + +{{related}} -| Feature | Setup | -| --- | --- | -| **Buttons, menus, and shortcuts** | Enable **Interactivity & Shortcuts** and use the same connection-specific Events Request URL as the **Interactivity Request URL**. | \ No newline at end of file +- [Channels](/agent-platform/channels) +- [Set up Microsoft Teams](/agent-platform/channels/microsoft-teams) +- [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file diff --git a/agent-platform/channels/telegram.mdx b/agent-platform/channels/telegram.mdx index e178f9c5b..8e2b8ffcf 100644 --- a/agent-platform/channels/telegram.mdx +++ b/agent-platform/channels/telegram.mdx @@ -3,226 +3,268 @@ title: Set up Telegram sidebarTitle: Telegram --- -[Back to messaging channels](/agent-platform/channels#messaging-or-digital-channels) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect a Telegram bot to your agent so users reach it in private chats, groups, and supergroups. Artemis registers the Telegram webhook for you and protects it with a generated secret, so you never call `setWebhook` yourself. +Connect a Telegram bot to your agent so users reach it in private chats, groups, and supergroups. You create the bot in Telegram and give Artemis its username and token. Artemis then registers a protected webhook with Telegram for you. -You create the bot in Telegram, then hand Artemis two values from it. Everything after that happens automatically when you create the connection. +The setup requires: + +1. [Create the Telegram bot](#create-the-telegram-bot) with BotFather. +2. [Artemis channel configuration](#artemis-channel-configuration): enter the bot's username and token, then create the connection. +3. [Verify the connection](#verify-the-connection) in a private chat, a group, and with buttons and media. + +After you create the connection, Telegram posts each update to Artemis, and the agent replies in the same chat. + +**Important considerations** + +- **The bot username selects the connection**: Artemis builds the webhook path from it and routes each update by it. You can't change it after creation. +- **Artemis registers the webhook for you**: Don't call `setWebhook` yourself. Telegram keeps one webhook per bot, so a manual call replaces the one Artemis registered and stops the connection. +- **One active connection per bot token**: Artemis rejects a second active connection that uses the same token, so it can't silently replace the first one's webhook. +- **Treat BotFather messages as secrets**: Anyone with the bot token can call the Bot API. Keep it out of tickets, screenshots, browser code, logs, and client-side configuration. + +## Prerequisites + +Confirm these before you start. + +- A Telegram account to talk to BotFather. +- An Artemis runtime reachable over public HTTPS, with outbound access to `api.telegram.org`. +- Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. + +--- ## How Artemis routes Telegram messages -Four pieces carry the integration, and each one does a different job. Confusing them causes most setup failures. +Four pieces carry the integration. You supply the first two, and Artemis manages the rest. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Bot Username** | BotFather | Routes incoming updates. Artemis puts the normalized username in the webhook path, then matches the last path segment to this connection. | -| **Bot Token** | BotFather | Authorizes every outbound call Artemis makes to the Telegram Bot API, including `setWebhook`, `sendMessage`, typing indicators, callback answers, and media downloads. | -| Secret token | Artemis | Verifies that an incoming update really came from Telegram. Artemis generates it, stores it encrypted, and never asks you for it. | -| Webhook URL | Artemis | Receives updates from Telegram. Artemis builds it from your bot username and registers it during creation. | +| Piece | Owner | What it does | +|---|---|---| +| **Bot Username** | BotFather | Routes incoming updates. Artemis puts the normalized username at the end of the webhook path and matches each update to this connection by it. | +| **Bot Token** | BotFather | Authorizes every outbound Bot API call: `setWebhook`, `sendMessage`, typing indicators, callback answers, and media downloads. | +| Secret token | Artemis | Proves each update came from Telegram. Artemis generates it, encrypts it, and never asks you for it. | +| **Webhook URL** | Artemis | Receives updates. Artemis builds it from the bot username and registers it during creation. | -Because the username sits in the URL path, you can't change it after creation. Create a new connection if you need to point at a different bot. +--- ## Create the Telegram bot -Do this work in Telegram before you open Artemis. BotFather is a bot itself, so you create your bot by holding a chat with it rather than by filling in a web form. See Telegram's [introduction for developers](https://core.telegram.org/bots) if you've never built a bot before. +Do this in Telegram before you open Artemis. Select **Open BotFather** or **Open Bot API documentation** in the setup guide to jump straight there. - Search Telegram for `@BotFather`, or open [t.me/botfather](https://t.me/botfather) from any device signed in to your account. Several accounts imitate BotFather, so confirm the blue verification badge beside the name before you send anything. A fake BotFather exists to harvest tokens. - - Select **Start** if you've never used it. BotFather replies with its command list. + 1. Search Telegram for `@BotFather`, or open [t.me/botfather](https://t.me/botfather). + 2. Confirm the blue verification badge beside the name. Fake BotFather accounts exist to harvest tokens. + 3. Select **Start**. - Send `/newbot`. BotFather asks two questions in turn. - - First it asks for a name, which is the title users see at the top of the chat. Spaces and most characters work here, and you can change it later. - - Then it asks for a username, which is permanent and must be unique across Telegram. Usernames run 5 to 32 characters, accept Latin letters, numbers, and underscores, ignore case, and must end in `bot`. BotFather rejects a taken username and asks again, so have a second choice ready. + 1. Send `/newbot`. + 2. Enter a display name. Users see it at the top of the chat, and you can change it later. + 3. Enter a username. It must be 5 to 32 Latin letters, numbers, or underscores, and end in `bot`. - Choose carefully. Telegram never lets you change a bot username, and Artemis builds the webhook path from it, so a rename means a new bot and a new connection in both systems. - - BotFather confirms with a message containing the bot link and the token. The token is the long string after the numeric bot ID and a colon. + Choose the username carefully. Telegram never lets you change it, and Artemis builds the webhook path from it. BotFather replies with the bot link and the token. - - Copy the username from the confirmation message without the `t.me/` prefix that surrounds it in the link. Artemis strips a leading `@` and stores the normalized value, so either form works. Nothing else routes: a display name, a numeric bot user ID, a chat ID, a token fragment, or a full URL all fail. - - Copy the token separately. Telegram formats it as a tappable code block, so tapping or clicking it copies the whole value. + + 1. Copy the username without the `t.me/` prefix. Artemis strips a leading `@`, so either form works. + 2. Copy the full token, including the numeric bot ID and the colon before the secret part. - To retrieve either value later, send `/mybots`, select the bot, and select **API Token**. BotFather shows the username and token again without creating anything new. + To retrieve either value later, send `/mybots`, select the bot, and select **API Token**. - - Return to BotFather and use these commands to control what users see before and during a chat. Each one prompts you to pick the bot first. + + Use these BotFather commands to shape what users see. They don't affect message delivery or replace the webhook. | Command | What it sets | - | ------- | ------------ | - | `/setname` | The title users see at the top of the chat. This one you can change whenever you like. | - | `/setdescription` | The text on the empty chat screen, shown before a user selects **Start**, up to 512 characters. | - | `/setabouttext` | The short line on the bot's profile page, which travels with the link when someone shares the bot, up to 120 characters. | - | `/setuserpic` | The bot's profile photo. | - | `/setcommands` | The command menu Telegram suggests as a user types `/`. | - - These shape discovery only. They don't affect message delivery, and they don't replace the webhook Artemis registers. Changes can take a few minutes to appear. Telegram documents the full command list under [BotFather](https://core.telegram.org/bots/features#botfather), and offers the same settings through the BotFather Mini App if you prefer a visual interface to chat commands. + |---|---| + | `/setdescription` | The text on the empty chat screen, before a user selects **Start** | + | `/setabouttext` | The short line on the bot's profile page | + | `/setuserpic` | The bot's profile photo | + | `/setcommands` | The command menu Telegram suggests when a user types `/` | - - Artemis processes a group or supergroup message only when the message mentions the bot, replies to one of its messages, or uses `/start` or `/help`. Ordinary group chatter never reaches your agent. - - This holds whatever you set in BotFather. Telegram's own [privacy mode](https://core.telegram.org/bots/features#privacy-mode), which you toggle with `/setprivacy`, widens what Telegram sends when you disable it, and a bot added to a group as an admin receives everything regardless. Artemis still applies the mention and reply rule on top, so neither change alters what your agent sees, and the bot stays quiet in busy groups by design. - - One Telegram behavior does matter here: a privacy mode change takes effect only after you remove the bot from the group and add it back. + + Artemis processes a group or supergroup message only when it mentions the bot, replies to one of the bot's messages, or uses `/start` or `/help`. Ordinary group chatter never reaches the agent, even if you turn off [privacy mode](https://core.telegram.org/bots/features#privacy-mode) in BotFather. - - Create one bot for development and another for production, each with its own token and its own Artemis connection. Telegram allows a single webhook per bot, so sharing one bot across environments means the two registrations overwrite each other. + + Create one bot for development and another for production, each with its own token and its own Artemis connection. -The bot token authorizes every Bot API call for that bot, and it travels in the request URL. Treat it like a password: keep it out of tickets, screenshots, logs, browser code, and client-side configuration. If it leaks, send `/token` to BotFather to generate a replacement, then update the credential in Artemis. The old token stops working as soon as the new one issues. +--- -## Connect the bot in Artemis +## Artemis channel configuration -The connection stores your bot identity, binds the agent version that answers, and registers the webhook. Go to **Deployments** -> **Channels** -> **Telegram** -> **+ New** and complete the following. +Create the connection with the bot's values. Artemis registers the webhook as part of creation. -| Field | What it controls | -| ----- | ---------------- | -| **Display Name** | The label operators see in the connections list. Name it for the bot and the environment it serves, because a project can hold several Telegram connections. Routing ignores this value. | -| **Bot Username** | The routing key. Enter the BotFather username exactly, with or without a leading `@`. Artemis writes the normalized value into the webhook path and can't change it later. | -| **Bot Token** | The credential for every outbound Bot API call. Paste the complete token, including the numeric bot ID and the colon that precedes the secret portion. Artemis encrypts it on save. | -| **Environment** | The published environment whose active deployment answers incoming messages. Selecting one keeps the connection current as you promote new versions. Leave the working copy default only while you develop. | -| **Provider Verification Strength** | How far Artemis trusts Telegram's identity assertion when it links a user to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust the provider's assertions enough to base continuity and account-linking decisions on them. | -| **Initial Status** | Whether the connection starts handling messages. **Active** takes traffic immediately. **Inactive** saves the configuration in a disabled state, which suits a connection you're staging ahead of a launch. | +1. Open Artemis and select the project. +2. Go to **Deployments** -> **Channels** -> **Telegram** -> **+ New**. The **New Telegram Connection** dialog opens, with the setup guide on the left and the connection fields on the right. +3. Configure the fields: -### What happens when you select Create + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see in the connections list. Routing ignores it. | + | **Bot Username** | BotFather's confirmation message | The routing key. Enter the exact BotFather username, preferably without `@`. Don't enter the display name, a numeric bot or chat ID, a token fragment, or a `t.me` URL. | + | **Bot Token** | BotFather's confirmation message | Authorizes every outbound Bot API call. Artemis encrypts it on save. | + | **Environment** | Your published environments | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Telegram's identity assertion when it links a user to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | **Active** takes traffic immediately. **Inactive** saves the connection disabled until you activate it. | -Artemis completes the Telegram-side registration in one step, so you don't touch the Bot API yourself. +4. Select **Create**. -Artemis generates a high-entropy secret token, calls `setWebhook` with the URL built from your bot username, and subscribes to `message` and `callback_query` updates only. It also drops any updates left pending from an earlier webhook on that bot, so stale traffic can't enter the new connection. Messages users sent before you created the connection won't appear, by design. +When you select **Create**, Artemis completes the Telegram side in one step: -If registration fails, Artemis rolls the whole creation back rather than leaving a connection that can't receive anything. A conflict at this point means the token already belongs to another active Telegram connection in the project. Telegram permits one webhook per bot, so Artemis refuses the second connection instead of silently replacing the first one's webhook. +- Generates a high-entropy secret token and stores it encrypted. +- Calls `setWebhook` with the connection-specific URL, which ends with the normalized bot username. +- Subscribes to `message` and `callback_query` updates only. Telegram channel posts and other update types stay outside the connection. +- Drops updates still pending from an earlier webhook, so stale events never reach the new connection. -## Verify the connection +If registration fails, Artemis rolls back the creation rather than leaving a connection that can't receive anything. -Run these checks before you hand the bot to users. Each one exercises a different path, and a bot that answers private messages can still fail in groups or on buttons. +--- - - - Open the bot by its exact username, select **Start**, and send a short message you can search for later. Confirm you get one reply and that Artemis opens a single session. - +## Verify the connection - - Send `/start`, then open a deep link carrying a start payload if your agent uses one. Artemis treats the command as a welcome action and passes the payload through as its value, so your agent can branch on where the user came from. Telegram documents the link format under [deep linking](https://core.telegram.org/bots/features#deep-linking). - +Each check exercises a different path. A bot that answers private messages can still fail in groups or on buttons. - - Add the bot to a group or supergroup, then address it by username, reply to one of its messages, and send `/start` or `/help`. Each should reach the agent. Send an unrelated message too, and confirm the bot ignores it. - +1. Open the bot by its exact username, select **Start**, and send a short, distinctive message. Confirm one session and one reply. +2. Send `/start`, or open a [deep link](https://core.telegram.org/bots/features#deep-linking) with a start payload. Artemis passes it to the agent as a welcome action, with the payload as its value. +3. Add the bot to a group, then mention it with `@BotUsername`, reply to one of its messages, and send `/start` or `/help`. Confirm each reaches the agent and an unrelated message doesn't. +4. Select a button on an inline keyboard. Confirm the loading spinner clears and the action returns to the same chat session. +5. Send each media type your agent accepts, including a caption at least once. - - Trigger a response that carries an inline keyboard and select a button. Confirm the loading spinner clears and the resulting action lands in the same chat session. - +Artemis downloads the largest photo size or the attached file through `getFile` before the agent processes it. - - Send a photo, document, audio file, video, and voice note, depending on what your agent accepts. Artemis downloads the largest photo size or the attached file before the agent processes it. Include a caption in at least one test, since captions travel separately from the file. - - +| Media type | What to confirm | +|---|---| +| `text` | The agent receives and answers it. | +| `photo`, `document`, `audio`, `video`, `voice` | The download succeeds and the agent processes the file and its caption. | +| `inline buttons` | The selection returns to the same session with the right action. | -## Manage the connection +--- -Opening a connection shows four tabs. The delete control sits beside the connection name. +## Telegram limits - - - **Connection Summary** reports the connection's state and identity. +Artemis applies these limits before it calls the Bot API. Design agent responses to fit them. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** | Date and time of creation. | - | **Updated** | Date and time of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | `Channel Connection`. | - | **Source ID** | The connection's internal identifier, useful when you raise a support request. | +| Area | Limit | +|---|---| +| Text | 1 to 4096 characters per message. Artemis sends a single ellipsis for an otherwise empty response. | +| Inline keyboards | Up to 10 rows. Button text up to 64 characters. | +| Callback data | 64 bytes. Keep authored action IDs and values short. | +| Media | 20 MB per file download. Artemis rejects larger files before upload. | +| Chats | Private chats, groups, and supergroups under the mention and reply rule. Artemis ignores channel posts. | - **Setup Instructions** shows the **Webhook URL** Artemis registered with Telegram and the normalized **Bot Username**, each with a copy control. The URL follows the form `https://{host}/api/v1/channels/telegram/webhook/{bot-username}` and ends with the username minus any leading `@`. +--- - Use the **Webhook URL** to confirm what Telegram should be calling. If `getWebhookInfo` reports a different URL, something outside Artemis re-registered the bot. - +## Security and lifecycle - - Update the bot token here when BotFather issues a new one. +A Telegram connection depends on two secrets and one webhook registration. - Artemis encrypts the stored token and never displays it again, so the field stays empty until you enter a replacement. Entering a new value and selecting **Save Credentials** overwrites the old one. +- **Secret header**: Telegram returns the generated secret in the `X-Telegram-Bot-Api-Secret-Token` header on every update. Artemis compares it with the stored value before processing, so any proxy in front of Artemis must preserve the header. +- **Bot token**: It authorizes every Bot API call and appears in request URLs. Store it only in Artemis, and redact it from logs and diagnostics. +- **Token rotation**: If BotFather revokes or regenerates the token, update it in the **Credentials** tab so Artemis can send messages and re-register the webhook. +- **Diagnosis**: Use `getWebhookInfo` only through a secure operator tool to confirm the URL and last error. Never call `setWebhook` or delete the webhook outside Artemis. +- **Duplicates**: Artemis deduplicates on Telegram's `update_id`, so a Telegram retry never creates a second agent turn. - Turn on **Use Auth Profile** to draw the credential from a stored authentication profile instead of holding a token on this connection. +--- - Rotate the credential whenever BotFather revokes or regenerates the token. Until you do, Artemis can neither re-register the webhook nor send messages, because both calls carry the old token. - +## Manage the channel connection - - Adjust how the connection presents itself and how it handles responses. +Open a Telegram connection from **Deployments** -> **Channels** -> **Telegram** to manage it. The page has a header, three tabs, and a summary panel on the right. + +**Header.** Shows the connection name, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this bot changes. +**Summary panel.** Stays visible on every tab. - Under **Telegram Settings**, **Bot Username** appears read-only. Artemis built the webhook path from it at creation, so changing it would break routing. Create a new connection to target a different bot. +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Telegram** and **Channel Connection**. | +| **Identifier** | The normalized bot username this connection routes on. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The URL Artemis registered with Telegram, with a copy control. If `getWebhookInfo` reports a different URL, something outside Artemis re-registered the bot. | +| **Created** and **Updated** | Date and time of creation and of the last change. | - Turn on **Enable Streaming** to send the agent's response to Telegram as the model produces it, rather than holding the message until the response completes. Streaming shortens perceived latency on long answers. + + + Artemis encrypts the token after you save it. Leave the field blank to keep the current value, or enter a new token to replace it. - **Authorization Message** controls what the user sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. + | Field | Description | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile from the list in place of the token field. | + | **Bot Token** | Replace it here whenever BotFather issues a new token. | - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, for example in a lead-in line before the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | + Select **Save Credentials** to apply your changes. + - Item variables resolve only inside the repeat block. Use the preview to check the wording, and remember it fills from live pending authorizations at runtime. + + Update how the connection behaves. **Telegram Settings** holds the provider-specific fields. + + | Setting | Description | + |---|---| + | **Display Name** | The label operators see in the connections list. | + | **Provider Verification Strength** | How far the runtime trusts Telegram's identity assertion. | + | **Bot Username** | Read-only, with a copy control. To target a different bot, create a new connection. | + | **Enable Streaming** | Sends the response to Telegram as the agent generates it. | + | **Chunk Size (characters)** | The minimum characters Artemis buffers before each update. Lower values feel faster and make more API calls. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. | + | **Webhook URL** | The registered URL, with a copy control. | + + Insert variables into the **Message template** from the chips below the editor, select **Show more** for the full list, and select **Show preview** to check the result. + + | Scope | Variables | + |---|---| + | Whole message | `{{total}}`, `{{completed}}`, `{{remaining}}` | + | Repeat block | `{{#authorizations}}` ... `{{/authorizations}}`, which repeats once per pending authorization | + | Inside the block | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | + + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers the bot. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic. Select **Save Changes** to apply the binding. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - A connection left on the working copy shows a warning, because the working copy is a development target that changes as you edit the agent. Bind the connection to a published environment before you put the bot in front of users. + A connection on **Working Copy (draft)** shows a warning, because the working copy changes as you edit the agent. Bind the connection to a published environment before you open the bot to users. Select **Save Changes** after you switch the environment. -## Telegram limits - -Telegram enforces these boundaries, and Artemis applies them before it calls the Bot API. Design your agent's responses to fit them. +--- -| Area | Limit | -| ---- | ----- | -| Text | Outbound messages run 1 to 4096 characters. Artemis substitutes a single ellipsis when a response would otherwise be empty. | -| Inline keyboards | Up to 10 rows, with button text capped at 64 characters. | -| Callback data | 64 bytes. Keep authored action IDs and values short enough to survive encoding. | -| Media | Files up to 20 MB download, which is the Bot API's own ceiling rather than an Artemis one. Artemis rejects anything larger before upload. | -| Channel posts | Not supported. The connection serves private chats, groups, and supergroups under the mention and reply rule. | +## Troubleshoot connection issues -## Operate the connection safely +Most failures trace to the token, the webhook registration, or the group mention rule. -A Telegram connection depends on two secrets and one webhook registration. Protect all three. +| Symptom | Likely cause | Recommended action | +|---|---|---| +| Creation fails with a webhook registration error | Artemis can't reach Telegram or the token is wrong | Verify the Bot Token, the public HTTPS runtime URL, outbound access to `api.telegram.org`, and that BotFather allows `setWebhook` for the bot. | +| Creation returns a conflict | The token already belongs to another active Telegram connection in the project | Reuse or deactivate that connection instead of replacing its webhook. | +| Updates return 401 | An external `setWebhook` call replaced the secret, or a proxy dropped the secret header | Re-save or recreate the connection in Artemis, and preserve `X-Telegram-Bot-Api-Secret-Token`. | +| Private messages don't arrive | The user hasn't started the bot, or the webhook points elsewhere | Confirm the user selected **Start**, `getWebhookInfo` shows this connection's URL, `allowed_updates` includes `message`, and the connection is **Active**. | +| Private chats work but groups don't | The message doesn't meet the mention and reply rule | Mention the exact bot username or reply to its message, test `/start` or `/help`, and confirm the bot is a group member. | +| Text works but buttons don't | Callback updates fail or the action is gone | Confirm `allowed_updates` includes `callback_query`, the callback payload fits 64 bytes, and the authored action still exists. | +| Text works but files fail | Unsupported type, oversized file, or a changed token | Confirm your agent accepts the media type, `getFile` succeeds with the current token, the file is 20 MB or smaller, and your attachment policy accepts it. | +| Messages sent before creation never arrive | Expected behavior | The initial `setWebhook` call drops pending updates so stale events can't enter the new connection. | -The secret token is separate from the bot token. Telegram returns it in the `X-Telegram-Bot-Api-Secret-Token` header on every update, and Artemis compares it with the encrypted stored value using a constant-time check before processing anything. A proxy that strips unrecognized headers breaks this check, so preserve the header end to end. +--- -Never call `setWebhook` yourself for a connected bot. Telegram keeps one webhook per bot, so registering another URL or deleting the webhook outside Artemis stops the connection until you re-save or recreate it. Use `getWebhookInfo` for diagnosis only, run it through a secure operator tool, and keep the real token out of any transcript you share. +## Telegram reference -Artemis deduplicates on Telegram's `update_id`, so a Telegram retry doesn't produce a duplicate agent turn. +Use these pages when you need detail beyond what this article covers. -## Troubleshooting +| Resource | Use it for | +|---|---| +| [Bots: an introduction](https://core.telegram.org/bots) | How Telegram bots work. | +| [BotFather](https://core.telegram.org/bots/features#botfather) | Every BotFather command. | +| [Privacy mode](https://core.telegram.org/bots/features#privacy-mode) | What Telegram sends a bot in groups. | +| [Bot API](https://core.telegram.org/bots/api) | `setWebhook`, `getWebhookInfo`, and message limits. | -Match the symptom to the check. Most failures trace to the token, the webhook registration, or the group mention rule. +{{related}} -| Symptom | What to check | -| ------- | ------------- | -| Creation fails with a webhook registration error | Verify the bot token, confirm the Artemis host is reachable over public HTTPS, confirm outbound access to `api.telegram.org`, and confirm BotFather permits `setWebhook` for the bot. | -| Creation returns a conflict | The token already belongs to another active Telegram connection in this project. Reuse that connection or deactivate it rather than replacing its webhook. | -| Updates return 401 | An external `setWebhook` call may have replaced the secret, or a proxy dropped the `X-Telegram-Bot-Api-Secret-Token` header. Re-save or recreate the connection and preserve the header. | -| Private messages don't arrive | Confirm the user selected **Start**, check that `getWebhookInfo` points at this connection's URL, and confirm the connection is active. | -| Private chats work but groups don't | Mention the exact bot username or reply to one of its messages, test `/start` and `/help`, and confirm the bot is a member of the group. Disabling privacy mode in BotFather doesn't make Artemis process unmentioned chatter. | -| Text works but buttons don't | Confirm the callback payload fits within 64 bytes and that the authored action still exists. | -| Text works but files fail | Confirm your agent accepts the media type, that the file is 20 MB or smaller, and that your attachment policy allows it. A failure here often means the token changed, since Artemis downloads through the Bot API. | -| Messages sent before creation never arrive | Expected. The initial registration drops pending updates so stale events can't enter the new connection. | +- [Channels](/agent-platform/channels) +- [Set up WhatsApp](/agent-platform/channels/whatsapp) +- [Set up Slack](/agent-platform/channels/slack) \ No newline at end of file diff --git a/agent-platform/channels/twilio.mdx b/agent-platform/channels/twilio.mdx index 2e368c8f5..ab549e535 100644 --- a/agent-platform/channels/twilio.mdx +++ b/agent-platform/channels/twilio.mdx @@ -5,173 +5,130 @@ sidebarTitle: Twilio SMS [Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect a Twilio phone number to your agent so customers reach it over SMS and MMS. You prepare a messaging-capable sender in Twilio, hand Artemis the account credentials, and then point the number's incoming-message webhook at a connection-specific URL that Twilio signs on every request. +Connect a Twilio phone number to your agent so customers reach it over SMS and MMS. You prepare a messaging-capable sender in Twilio, enter its account credentials in Artemis, then point the number's incoming-message webhook at a connection-specific URL that Twilio signs on every request. The setup requires: -1. [Twilio setup](#twilio-setup): Choose the project, get a messaging-capable number, complete sender compliance, and copy the Account SID and Auth Token. -2. [Artemis channel configuration](#artemis-channel-configuration): Configure the connection using those credentials, then copy the generated webhook URL. -3. [Webhook configuration in Twilio](#webhook-configuration-in-twilio): Set the number's incoming-message webhook to that URL and select HTTP POST. +1. [Prepare the Twilio project and sender](#prepare-the-twilio-project-and-sender). +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +3. [Webhook configuration in Twilio](#webhook-configuration-in-twilio): set the number's incoming-message webhook. +4. [Verify the connection](#verify-the-connection) with signed two-way SMS and MMS. -After you complete the configuration, an SMS to your Twilio number opens a session in Artemis, the bound deployment answers it, and the reply goes back to the sender through Twilio's Messages API. +After setup, an SMS to your Twilio number opens a session in Artemis, and the agent's reply goes back through Twilio's Messages API. **Important considerations** -- **The reply doesn't travel in the webhook response**: Artemis returns an empty TwiML acknowledgement immediately and queues the agent, then sends the reply as a separate outbound API call. A 2xx on the webhook proves delivery of the inbound message and nothing more. -- **Twilio signs the webhook URL itself**: The signature covers the full external URL and the sorted form fields. Scheme, host, port, and path all participate, so a proxy that rewrites any of them breaks signature validation even though the request arrives intact. -- **One account boundary**: The Account SID, Auth Token, phone number, and any Messaging Service SID have to come from the same Twilio project or subaccount. Mixing a subaccount number with parent-account credentials fails in ways that look like a configuration error. -- **Compliance sits outside Artemis**: Sender registration, consent, and opt-out rules belong to Twilio and the carriers. A working webhook doesn't exempt your traffic from them. +- **The Twilio phone number selects the connection**: Save the number in E.164 format, such as `+15551234567`. Artemis resolves the connection from the encoded number in the webhook path, then confirms the inbound `To` field matches. A friendly connection name isn't a valid identifier. +- **The reply doesn't travel in the webhook response**: Artemis returns an empty TwiML response immediately and sends the agent's reply separately. A 2xx proves only that Twilio delivered the inbound message. +- **Twilio signs the exact URL**: Scheme, host, port, path, the encoded plus sign, and form values all participate in signature validation. A proxy that rewrites any of them breaks it. +- **One account boundary**: The Account SID, Auth Token, phone number, and optional Messaging Service must come from the same Twilio project or subaccount. ## Prerequisites -- A Twilio account with access to the project or subaccount that owns the sender and its billing. -- A messaging-capable Twilio phone number for the destination countries, in E.164 format with the leading plus and country code. -- Any sender registration your traffic needs, such as [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) brand and campaign registration for United States long-code traffic. +Confirm these before you start. + +- Access to the Twilio project or subaccount that owns the sender and its billing. +- A messaging-capable Twilio number for the destination countries, with any sender registration your traffic needs, such as [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) for US long codes. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- ## How Artemis routes Twilio SMS messages -Twilio calls a URL you choose per phone number, so Artemis puts the connection identifier in the path rather than reading it from the payload. +Twilio calls a URL you set per number, so Artemis puts the number in the path. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **Connection Identifier** | You | Routes inbound messages. Artemis appends it to the webhook path and resolves the connection from that segment, so the identifier has to survive in the URL exactly as Twilio calls it. | -| **Account SID** | Twilio | Identifies the account for outbound calls to the Messages API and for authenticated MMS downloads. It starts with `AC`. | -| **Auth Token** | Twilio | Does two jobs. Artemis uses it to validate the `X-Twilio-Signature` header on every inbound request, and to authenticate outbound API calls. | -| **Messaging Service SID** | Twilio | Optional. When present, Artemis sends replies through that service instead of replying from the inbound number. It starts with `MG`. | -| **Webhook URL** | Artemis | Receives the incoming-message callback. It ends with the connection identifier, and its exact external form is part of the signature. | +| Piece | Owner | What it does | +|---|---|---| +| **Twilio Phone Number** | Twilio | Routes inbound messages. Artemis encodes it in the webhook path, so a leading plus becomes `%2B`, and checks that it matches the inbound `To` field. | +| **Account SID** | Twilio | Identifies the account for the Messages API and authenticated MMS downloads. Starts with `AC`. | +| **Auth Token** | Twilio | Validates `X-Twilio-Signature` on inbound requests and authorizes outbound API calls. | +| **Messaging Service SID** | Twilio | Optional. When set, Artemis sends replies through that service. Starts with `MG`. | +| **Webhook URL** | Artemis | Receives the incoming-message callback at `/api/v1/channels/twilio_sms/webhook/{number}`. | -Artemis keys each conversation to the Twilio number and the customer number together, so the same person messaging two of your Twilio numbers holds two separate sessions. +Artemis keys each conversation as `twilio_sms:{To}:{From}`, so a different sender or Twilio number starts a separate conversation. --- -## Twilio setup +## Prepare the Twilio project and sender -Do this work in the [Twilio Console](https://www.twilio.com/console) before you open Artemis. +Do this in Twilio before you open Artemis. Select **Open Twilio Console** or **Open Messaging Services** in the setup guide to jump straight there. - - Sign in to the Twilio Console, then use the account selector at the top of the page to switch to the project or subaccount that owns the production phone number and its billing. - - Everything you collect from here has to come from this one account boundary. Twilio scopes the Auth Token to the account, so credentials from a parent account can't authenticate a subaccount's traffic. + + In the [Twilio Console](https://www.twilio.com/console), switch to the project or subaccount that owns the production number and billing. Every value you collect must come from this one account. - - 1. Go to **Phone Numbers** -> **Manage** -> **Active numbers**. - 2. Confirm the number you intend to use lists SMS capability, and MMS as well if your agent will handle media. - 3. If you need a new number, buy one from **Phone Numbers** -> **Buy a number**, filtering by the capabilities and country you need. - - Keep the full E.164 value, including the leading plus and country code. Capability varies by country, so a number that sends SMS in one market may not support MMS in another. + + 1. Go to **Phone Numbers** -> **Manage** -> **Active numbers**, or buy a number from **Buy a number**. + 2. Confirm it supports SMS, and MMS if the agent handles media, for the destination countries. + 3. Keep the full E.164 value, including the leading plus and country code. - Finish the registration, sender-verification, consent, and opt-out requirements Twilio shows for your countries and traffic type. - - United States long-code traffic needs A2P 10DLC brand and campaign registration. Carriers filter unregistered traffic rather than failing it loudly, so messages appear to send and never arrive. Twilio surfaces this as error 30034. - - Configuring a webhook doesn't bypass any of this. Start compliance early, because it waits on external review rather than on you. + Finish the registration, sender verification, consent, opt-out, and regional requirements Twilio shows for your countries and traffic type. A configured webhook doesn't bypass carrier or regulatory rules. - 1. Open the Twilio Console dashboard for the selected account. - 2. Find the account information panel, which shows the **Account SID** and the **Auth Token**. - 3. Copy the `AC`-prefixed Account SID, then reveal and copy the Auth Token. - - The Auth Token authenticates outbound API calls and validates inbound request signatures, so treat it as a high-value secret and store it in your secret manager rather than in a ticket or a shared document. + From the account information panel on the Twilio Console dashboard, copy the `AC`-prefixed **Account SID**, then reveal and copy the **Auth Token**. - A Messaging Service is optional. Use one when you want Twilio to pick a sender from a pool, apply sticky sender behavior, or carry an A2P campaign registration. - - 1. Go to **Messaging** -> **Services** and create a service, or open an existing one. - 2. Add your phone number to the service's sender pool. Twilio's [sender pool guidance](https://help.twilio.com/articles/4402705042075-Managing-a-Messaging-Service-Sender-Pool) covers the rules. - 3. Copy the `MG`-prefixed SID. - - Leave the SID out of the Artemis connection to reply from the inbound number instead. Twilio's [Messaging Services documentation](https://www.twilio.com/docs/messaging/services) explains what each mode changes. - - - - A trial project restricts which recipients and senders you can use, and adds branding to outbound messages. - - Prove production behavior on an upgraded account with an approved sender. A trial test that works tells you the wiring is right, not that your launch will work. + A Messaging Service is optional. To use one, go to **Messaging** -> **Services**, add your number to its **Sender Pool**, configure inbound handling at the service or number level, and copy the `MG`-prefixed SID. +Twilio trial restrictions still apply. Trial projects may limit recipients, sender choices, or message branding. Prove production behavior with an upgraded account and an approved sender before launch. + --- ## Artemis channel configuration -Create the connection before you configure the Twilio webhook. The callback URL contains the connection identifier, so you can't finalize it in Twilio until Artemis has generated it. +Create the connection before you configure the Twilio webhook. The callback URL contains the encoded phone number, so you can't finalize it until the identifier exists. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **Twilio SMS** -> **+ New**. -3. Configure the following fields: - - | Artemis connection field | Source / Notes | - |---|---| - | Display Name | The label operators see in the connections list. Name it for the sender and the environment it serves, because a project can hold several Twilio connections. Routing ignores this value. | - | Connection Identifier | The routing key, which Artemis writes into the webhook path. Choose a short, stable, URL-safe value that identifies this sender. You can't change it after creation, because the webhook URL is built from it. | - | Account SID | Identifies the Twilio account for outbound calls and MMS downloads. From the account information panel in the Twilio Console dashboard. | - | Auth Token | Validates the signature on inbound requests and authenticates outbound API calls. From the same account as the Account SID. | - | Messaging Service SID | Optional. Supply it to send replies through that service. Leave it empty to reply from the number that received the message. | - | Environment | The published environment whose active deployment answers incoming messages. Leave the working copy default only while you develop. | - | Provider Verification Strength | How far Artemis trusts Twilio's identity assertion when it links a sender to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Whether the connection starts handling messages. **Active** takes traffic immediately. **Inactive** saves the configuration in a disabled state, which suits a connection you're staging ahead of a launch. | +2. Go to **Deployments** -> **Channels** -> **Twilio SMS** -> **+ New**. The **New Twilio SMS Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see. Name it for the sender and environment. Routing ignores it. | + | **Twilio Phone Number** | **Active numbers** | The routing identifier. Enter the exact E.164 value, including the plus sign and country code. | + | **Account SID** | Twilio Console dashboard | Used with the Auth Token for the Messages API and authenticated MMS downloads. | + | **Auth Token** | Twilio Console dashboard | Validates inbound `X-Twilio-Signature` and authorizes outbound calls. Use the token from the same account. | + | **Messaging Service SID** | **Messaging** -> **Services** | Optional. When set, Artemis sends with `MessagingServiceSid`. Leave it empty to reply from the inbound number. | + | **Environment** | Your published environments | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Twilio's identity assertion when it links a sender to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | Keep it **Active**. | 4. Select **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab.
- The URL ends with your connection identifier. Copy it exactly, because Twilio signs the complete URL and any difference invalidates the signature. - -### Validation checklist - -| Validation item | Expected result | -|:---|:---| -| Select the Twilio account | Account SID, Auth Token, phone number, and any Messaging Service all come from one project or subaccount. | -| Confirm sender capability | Number lists SMS capability for the destination countries, and MMS if the agent handles media. | -| Complete compliance | Sender registration, consent, and opt-out requirements finished for the traffic type and region. | -| Create the Artemis connection | Connection saved as Active with a stable connection identifier and the account credentials. | -| Copy the webhook URL | Webhook URL copied from the **Overview** tab, ending with the connection identifier. | -| Configure the Twilio webhook | The number's incoming-message webhook points at that exact URL with HTTP POST selected. | -| Bind a deployment | The connection's **Deployment** tab shows a runnable active deployment. | -| Send a real SMS | Test message reaches the agent and the reply arrives once. See [Verify the connection](#verify-the-connection). | +5. Copy the **Webhook URL** from the connection's summary panel. It ends with the encoded number, where a leading plus appears as `%2B`. --- ## Webhook configuration in Twilio -Twilio calls this URL every time the number receives a message. Configure it on the number itself, or on the Messaging Service when that service owns inbound handling. - - - - For a direct number, go to **Phone Numbers** -> **Manage** -> **Active numbers** and select the number. +Twilio calls this URL every time the sender receives a message. - For a Messaging Service that owns inbound handling, open the service and use its integration settings instead. Configure one or the other, because two handlers pointing at the same connection produce duplicate replies. - +1. Confirm the Artemis connection exists and is **Active**. Artemis resolves the connection from the encoded number before it verifies the signature or reads the form body. +2. Open the sender's incoming-message configuration. For a direct number, go to **Phone Numbers** -> **Manage** -> **Active numbers** and select the number. For a Messaging Service that owns inbound handling, use the service's **Integration** settings. +3. Paste the exact public HTTPS URL into **A message comes in**. Keep the encoded phone-number segment. +4. Select **HTTP POST**, and save. Twilio sends `application/x-www-form-urlencoded` fields including `MessageSid`, `AccountSid`, `From`, `To`, `Body`, `NumMedia`, and any `MediaUrlN`. +5. Keep the public callback URL exact. Twilio signs the full URL plus the sorted form fields with HMAC-SHA1 and the Auth Token. Artemis validates using its configured public Runtime URL, not an internal proxy URL. - - 1. Scroll to the **Messaging** section of the number's configuration. - 2. In the **A message comes in** field, select **Webhook**. - 3. Paste the Artemis **Webhook URL** exactly as shown, including the connection identifier at the end. - 4. Select **HTTP POST** from the method dropdown. - 5. Select **Save**. +Artemis returns HTTP `200` with an empty TwiML response and queues the agent. The agent's reply follows separately through the Messages API. - Twilio sends `application/x-www-form-urlencoded` POST fields including `MessageSid`, `AccountSid`, `From`, `To`, `Body`, `NumMedia`, and any `MediaUrl` fields. Twilio's [incoming message webhook reference](https://www.twilio.com/docs/usage/webhooks/sms-webhooks) lists them all. - +Proxy rewriting can break signature verification. Configure the Runtime public base URL to the same external URL Twilio calls, and forward `X-Twilio-Signature` unchanged. - - Twilio signs the complete URL plus the sorted form fields using HMAC-SHA1 with your Auth Token, then sends the result in `X-Twilio-Signature`. Artemis validates the signature using its configured public base URL. - - Configure that base URL to the same external address Twilio calls, and forward the `X-Twilio-Signature` header unchanged. HTTPS termination and reverse-proxy host and protocol settings all have to agree, because scheme, host, port, path, and form values all participate in validation. - +### Validation checklist - - Artemis returns HTTP 200 with an empty TwiML response straight away and queues the agent. Twilio treats that as an acknowledgement and sends nothing to the customer. +Work down this list once per connection. - The agent's reply follows separately through the Messages API. Twilio expects a response within 15 seconds and calls the fallback webhook when the primary fails or times out, which is why the acknowledgement returns before the agent runs. - - +| Validation item | Expected result | +|:---|:---| +| Prepare the sender | Account SID, Auth Token, number, and any Messaging Service come from one account, with compliance complete. | +| Create the Artemis connection | Saved as **Active** with the E.164 number. | +| Configure the webhook | **A message comes in** points at the exact URL, with **HTTP POST**. | +| Send a real SMS | One session and exactly one reply. | --- @@ -179,103 +136,98 @@ Twilio calls this URL every time the number receives a message. Configure it on Artemis doesn't synthesize Twilio requests, so a real SMS is the only end-to-end proof. -1. From an allowed recipient, send a short SMS to the Twilio number that you can search for later.
- On a trial project, the recipient has to be a verified caller ID. -2. Confirm Twilio reports a 2xx webhook result and that Artemis opens one session. -3. Check that the agent replies once to the original sender.
- The reply arrives from the inbound Twilio number, or from the Messaging Service when you supplied its SID. The empty TwiML acknowledgement isn't the reply, so a 2xx with no message means the outbound path failed. -4. Send a second message from the same customer number to the same Twilio number, and confirm it continues the existing session rather than starting a new one.
- A different sender or recipient number opens a separate conversation. -5. Send an MMS where the number, destination, and carrier support it, and confirm the agent handles the downloaded attachment. -6. Repeat the whole test on an upgraded account with the production sender and an ordinary recipient, then check opt-in and opt-out handling, delivery status, throughput, and per-segment cost. +1. From an allowed recipient, send a unique SMS to the Twilio number. Confirm Twilio reports a 2xx webhook result and Artemis creates one session. +2. Confirm the agent replies to the original `From` number, from the inbound Twilio number or the configured Messaging Service. The empty TwiML is only an acknowledgement. +3. Send a second message from the same customer to the same Twilio number. Confirm it continues the `twilio_sms:{To}:{From}` session. +4. Send MMS only where the number, destination, and carrier support it. Artemis authenticates downloads from allowed Twilio hosts and applies attachment type and size policy. +5. Repeat with the production sender and a normal recipient. Validate opt-in, opt-out, regional registration, throughput, delivery status, and segmentation costs. + +| Input | What to confirm | +|---|---| +| `SMS text` | The agent receives and answers it. | +| `MMS image`, `MMS video`, `MMS audio`, `MMS file` | The download succeeds and the agent processes the file. | --- ## SMS behavior and limits -SMS is a plain-text channel with carrier economics attached, which changes how you author agent responses. +SMS is plain text with carrier economics attached. | Area | Behavior | -| ---- | -------- | -| Formatting | SMS carries plain text only. Markdown, buttons, and rich cards have no equivalent, so author replies that read correctly without them. | -| Message length | Carriers split long messages into multiple segments, and each segment bills separately. Unicode characters reduce the per-segment character count, so test representative content for your target countries. | -| Delivery retries | Twilio delivers webhooks at least once and makes no ordering guarantee, so the same inbound message can arrive more than once. | -| Media | MMS availability depends on the number, the destination, and the carrier. Artemis authenticates downloads from allowed Twilio hosts using the Account SID and Auth Token, then applies attachment type and size policy. | -| Timeout | Twilio expects a webhook response within 15 seconds and falls back to the secondary handler after that. | -| Compliance | Consent, opt-out keywords, and sender registration apply to every message regardless of how the agent behaves. | +|---|---| +| Formatting | Plain text only. Markdown, buttons, and rich cards have no SMS equivalent. | +| Length | Carriers split long messages into segments, and each segment bills separately. Unicode shrinks the per-segment character count. | +| Retries | Twilio can deliver the same webhook more than once. Artemis deduplicates on `MessageSid`. | +| Media | MMS depends on the number, destination, and carrier. | +| Compliance | Consent, opt-out keywords, and sender registration apply to every message. | --- -## Secure the connection - -Twilio authentication rests on one credential doing two jobs, and on a URL that both sides have to match exactly. +## Security and transport boundaries -Every inbound request carries `X-Twilio-Signature`. Artemis computes HMAC-SHA1 over the configured public callback URL and the sorted form parameters using the Auth Token as the key. Twilio's [security guide](https://www.twilio.com/docs/usage/security) describes the same calculation from the sending side. +One credential does two jobs, and the URL both sides see must match exactly. -Treat the external URL as signed data. Keep HTTPS termination, host, protocol, and port aligned with the public base URL you configured for Artemis, and pass the signature header through untouched. A reverse proxy that presents a different internal URL to Artemis breaks validation even though nothing about the message changed. - -The Auth Token validates inbound signatures and authorizes outbound sends, so rotate it in Twilio and Artemis as one coordinated change rather than two. A rotation applied on one side only stops inbound and outbound traffic at the same moment. - -Use separate Twilio subaccounts or senders, credentials, webhooks, and connections for development and production. +- **Signatures**: Inbound requests require `X-Twilio-Signature`. Artemis computes HMAC-SHA1 with the Auth Token, the configured public callback URL, and the sorted form parameters. +- **Signed URL**: Keep HTTPS termination and reverse-proxy host and protocol aligned with the Runtime public base URL. +- **Auth Token**: It protects inbound verification and outbound Basic authentication. Rotate it in Artemis and Twilio as one coordinated change. +- **MMS downloads**: Artemis uses the Account SID and Auth Token, accepts only allowed Twilio hosts, then applies attachment policy. +- **Environments**: Use separate subaccounts or senders, credentials, webhooks, and connections for development and production. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **Twilio SMS** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its environment badge, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to configure in Twilio and the **Connection Identifier** it ends with, each with a copy control. Compare the URL here with what Twilio actually calls whenever signature validation fails. - +**Summary panel.** Stays visible on every tab. + +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Twilio SMS** and **Channel Connection**. | +| **Identifier** | The Twilio phone number this connection routes on. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The incoming-message URL for Twilio, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + - Artemis encrypts credentials after you save them, so each field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new one to replace it. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credentials from a saved auth profile instead of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | **Account SID** | Replace it here if you move the sender to a different Twilio account or subaccount. | - | **Auth Token** | Replace it here the moment you rotate the token in Twilio, because inbound validation and outbound sends both stop until you do. | - | **Messaging Service SID** | Add or replace it to route replies through a service. Clear it to reply from the inbound number instead. | + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **Account SID** | Replace it if the sender moves to another Twilio account. | + | **Auth Token** | Replace it as soon as you rotate it in Twilio, because inbound validation and outbound sends both stop until you do. | + | **Messaging Service SID** | Add it to send through a service, or clear it to reply from the inbound number. | Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this sender changes. - - Under **Twilio SMS Settings**, **Connection Identifier** appears read-only. The webhook URL is built from it, so changing it would invalidate the URL configured in Twilio. Create a new connection to serve a different sender. + Update how the connection behaves. **Twilio SMS Settings** holds the provider-specific fields. - **Authorization Message** controls what the person sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. - - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | - - Item variables resolve only inside the repeat block. Keep the wording short, because SMS renders it as plain text and long templates split into extra segments. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Twilio's identity assertion. | + | **Twilio Phone Number** | Read-only, with a copy control. To serve another number, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Keep it short, because SMS renders plain text and long templates split into extra segments. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The incoming-message URL, with a copy control. | Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers SMS. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic and when someone deployed it. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - Check this pair when the channel connects but the agent behaves like an older build. The connection follows whatever the environment currently has deployed, not the version you last edited. Select **Save Changes** after you switch the environment. + Select **Save Changes** after you switch the environment. @@ -283,34 +235,34 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Most failures trace to the URL, the Auth Token, or the account boundary. + | Symptom | Likely cause | Recommended action | |---|---|---| -| Artemis reports no connection found | Twilio is calling a URL that doesn't end with this connection's identifier, or the connection isn't active | Compare the URL configured in Twilio with the **Webhook URL** on the **Overview** tab, including the trailing identifier, and confirm the connection is Active. | -| The webhook returns 401 | The signed URL or the Auth Token doesn't match | Compare the exact external URL Twilio called with the public base URL you configured for Artemis, preserve `X-Twilio-Signature` through your ingress, and confirm the Auth Token belongs to the same Account SID. | -| The webhook returns 200 but no session appears | The request carried nothing to process, or the queue is unhealthy | Send a message with a non-empty body or at least one media item, then check queue health. | -| Inbound works but no reply goes out | The outbound credential, sender ownership, compliance state, or deployment is wrong | Verify the Account SID and Auth Token, confirm the account owns the sender, check destination eligibility and registration, and confirm the bound environment has a runnable deployment. | -| The Messaging Service sends from the wrong number or fails | The service belongs to another account, or the sender isn't in its pool | Confirm the `MG` SID belongs to the same account and the intended number sits in its sender pool. Clear the SID to reply directly from the inbound number. | -| SMS works but MMS fails | Capability, media access, or attachment policy blocks it | Confirm carrier and number support for MMS, that the Twilio media URL is reachable from an allowed host, that the credentials authenticate the download, and that content type and size pass your attachment policy. | -| Customers receive duplicate replies | Two inbound handlers point at this connection, or Twilio retried | Confirm only one number or Messaging Service handler targets this connection, and deduplicate on `MessageSid` to absorb Twilio's retries. | -| Long messages cost or render unexpectedly | Carrier segmentation split the message | Shorten agent replies, test representative Unicode content, and check per-segment behavior for the destination countries. | +| Connection not found | Wrong URL, number, or inactive connection | Confirm Twilio calls the full URL ending in the encoded E.164 number, the saved identifier has the same leading-plus number, and the connection is **Active**. | +| Webhook returns `401` | Signed URL or Auth Token mismatch | Compare the exact external URL Twilio called with the Runtime public base URL, preserve `X-Twilio-Signature`, and confirm the Auth Token belongs to the same Account SID. | +| Webhook returns `200` but no session appears | Empty payload or queue issue | Send a payload with `MessageSid` and either a non-empty `Body` or `NumMedia` greater than zero, then check queue health. | +| Inbound works but outbound fails | Credentials, ownership, or deployment | Verify the Account SID and Auth Token, sender ownership, destination eligibility, compliance, and that the environment can run. | +| Messaging Service sends from the wrong number or fails | Service or pool mismatch | Confirm the `MG` SID belongs to the same account and the number is in its **Sender Pool**, or clear the SID to reply from the inbound number. | +| SMS works but MMS fails | Media support or policy | Confirm carrier and number support, Twilio media URL access, allowed host, Basic-auth credentials, content type, and attachment size policy. | +| Users receive duplicate replies | Two handlers or retries | Confirm only one number or service handler points at this connection, and account for Twilio retries with `MessageSid` deduplication. | +| Long messages cost or render unexpectedly | Carrier segmentation | Shorten replies, and test representative Unicode and long content for the target countries. | --- ## Twilio reference -Use these Twilio pages when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. | Resource | Use it for | -| -------- | ---------- | -| [Twilio Console](https://www.twilio.com/console) | Account credentials, active numbers, and Messaging Services. | -| [Incoming message webhooks](https://www.twilio.com/docs/usage/webhooks/sms-webhooks) | The form fields Twilio posts and how the incoming-message webhook behaves. | -| [Messaging webhooks overview](https://www.twilio.com/docs/usage/webhooks/messaging-webhooks) | The difference between incoming-message webhooks and status callbacks. | -| [Security](https://www.twilio.com/docs/usage/security) | How Twilio builds the signature and what participates in it. | -| [Messaging Services](https://www.twilio.com/docs/messaging/services) | Sender pools, sticky sender behavior, and service-level inbound handling. | -| [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) | Brand and campaign registration for United States long-code traffic. | +|---|---| +| [Incoming message webhooks](https://www.twilio.com/docs/usage/webhooks/sms-webhooks) | The form fields Twilio posts. | +| [Webhook security](https://www.twilio.com/docs/usage/security) | How Twilio builds the signature. | +| [Messaging Services](https://www.twilio.com/docs/messaging/services) | Sender pools and service-level inbound handling. | +| [A2P 10DLC](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) | US long-code registration. | {{related}} +- [Channels](/agent-platform/channels) - [Set up WhatsApp](/agent-platform/channels/whatsapp) -- [Set up Messenger](/agent-platform/channels/messenger) -- [Set up Instagram](/agent-platform/channels/instagram) \ No newline at end of file +- [Set up Zendesk](/agent-platform/channels/zendesk) \ No newline at end of file diff --git a/agent-platform/channels/whatsapp.mdx b/agent-platform/channels/whatsapp.mdx index 8c96bf4e1..176cfc2a2 100644 --- a/agent-platform/channels/whatsapp.mdx +++ b/agent-platform/channels/whatsapp.mdx @@ -78,22 +78,7 @@ Never append a phone number, connection ID, or provider slug to these routes you ## How Artemis routes WhatsApp events -Every inbound message follows the same path, whichever provider carries it. Knowing the path tells you where to look when a message goes missing. - -```mermaid -flowchart LR - A[Customer sends WhatsApp message] --> B[Provider posts callback to Artemis webhook route] - B --> C{Sender identifier matches a saved connection?} - C -- No --> D[Connection not found] - C -- Yes --> E{Inbound verification passes?} - E -- No --> F[Callback rejected] - E -- Yes --> G[Session created or resumed] - G --> H[Deployed agent runs] - H --> I[Reply sent through provider API with outbound credentials] - I --> J[Customer receives reply] -``` - -The runtime finds the connection by reading one field from each provider's callback body. That field must match the routing identifier you saved in Artemis. +Every inbound message follows the same path, whichever provider carries it. Knowing the path tells you where to look when a message goes missing. The runtime finds the connection by reading one field from each provider's callback body. That field must match the routing identifier you saved in Artemis. | Provider | Inbound field the runtime reads | Common mix-up | |---|---|---| diff --git a/agent-platform/channels/zendesk.mdx b/agent-platform/channels/zendesk.mdx index f6b8a2954..eb70b8289 100644 --- a/agent-platform/channels/zendesk.mdx +++ b/agent-platform/channels/zendesk.mdx @@ -3,286 +3,216 @@ title: Set up Zendesk sidebarTitle: Zendesk --- -[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital) +[Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect a Zendesk Sunshine Conversations app to your agent so customers reach it through any messaging channel that app already serves. Sunshine Conversations normalizes Web Widget, social channels, and SMS into one API, so Artemis integrates once and inherits every entry point the app carries. +Connect a Zendesk Sunshine Conversations app to your agent so customers reach it through any channel that app already serves. You map the app's App ID and API key into Artemis, register a connection-specific webhook, then verify messages, replies, and postbacks. The setup requires: -1. [Zendesk setup](#zendesk-setup): Select or create the Sunshine Conversations app, copy its App ID, and create an API key. -2. [Artemis channel configuration](#artemis-channel-configuration): Enter those values, then copy the generated webhook URL. -3. [Webhook configuration in Zendesk](#webhook-configuration-in-zendesk): Register that URL as a conversations integration and subscribe it to the message and postback triggers. +1. [Prepare the Sunshine Conversations app](#prepare-the-sunshine-conversations-app) and its API key. +2. [Artemis channel configuration](#artemis-channel-configuration): create the connection, then copy its Webhook URL. +3. [Register the webhook](#register-the-webhook) in the same app. +4. [Verify the connection](#verify-the-connection) with a complete customer conversation. -After the configuration is complete, a customer message on any channel connected to the app opens a session in Artemis, the bound deployment answers it, and the reply posts back into the same conversation as a business author. +After setup, a customer message on any channel connected to the app opens a session in Artemis, and the reply posts back into the same conversation as a business author. **Important considerations** -- **The App ID does two jobs**: It routes inbound events and identifies the app for outbound replies. The connection dialog asks for it twice, once as the routing identifier and once as a credential, and both have to name the same Sunshine Conversations app. -- **Two setup paths exist**: Zendesk Suite customers work in Admin Center, while accounts with a separate Sunshine Conversations license use the Sunshine Conversations dashboard. The values are the same either way; the navigation isn't. -- **Webhook verification is optional and needs middleware**: Artemis expects an `x-api-key` header carrying an HMAC of the raw body, which Sunshine Conversations doesn't send natively. Leave **Webhook Secret** empty unless something in front of Artemis generates that header. -- **Artemis doesn't create the customer entry point**: The app still needs a connected channel or client through which a customer can start a conversation. Registering the webhook adds no channel of its own. +- **App ID is both the routing key and the provider destination**: Artemis resolves inbound events from the App ID at the end of the webhook URL, and uses the payload's matching `app.id` for replies. Both App ID fields must identify the same Sunshine Conversations app. +- **Never expose the Key Secret**: The API Key ID and Key Secret authorize outbound messages for every conversation in the app. Store them only in Artemis, and rotate both together. +- **Webhook Secret isn't the API Key Secret**: It's optional, and only works when a sender or trusted middleware generates the `x-api-key` HMAC header Artemis expects. +- **Artemis doesn't create the customer entry point**: The app still needs a connected Sunshine Conversations integration or client through which a customer starts a conversation. ## Prerequisites -- A Sunshine Conversations app with at least one customer-facing channel already connected, such as Web Widget or a social channel. -- Zendesk Suite Professional or above with Agent Workspace activated, if you're working in Admin Center. The Conversations API page doesn't appear on lower plans. -- Administrator access in Zendesk, since only an administrator can create the API key. +Confirm these before you start. + +- A Sunshine Conversations app with at least one customer-facing integration, such as the Web Widget or a social channel. +- Administrator access in Zendesk. In Admin Center, the Conversations API page needs Zendesk Suite Professional or above with Agent Workspace. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- ## How Artemis routes Zendesk events -Artemis puts the App ID at the end of the webhook path and resolves the connection from that segment, then uses the matching app in the payload for replies. +Artemis puts the App ID at the end of the webhook path and resolves the connection from it. -| Piece | Who owns it | What it does | -| ----- | ----------- | ------------ | -| **App ID** | Zendesk | Routes inbound events. Artemis appends it to the webhook path, so the generic Zendesk webhook route alone can't resolve a connection. It also identifies the app on outbound calls. | -| **API Key ID** | Zendesk | The username half of the HTTP Basic credential Artemis uses to post replies. | -| **API Key Secret** | Zendesk | The password half. Zendesk shows it once at creation and never again. | -| **Webhook Secret** | You | Optional. When set, Artemis requires an `x-api-key` header carrying the lowercase hexadecimal HMAC-SHA256 of the exact raw request body, and rejects anything without a match. | -| **Webhook URL** | Artemis | Receives conversation events. It ends with the App ID, so the full URL matters rather than the route alone. | +| Piece | Owner | What it does | +|---|---|---| +| **App ID** | Zendesk | Routes inbound events from the URL, and identifies the app for replies. It appears in a public URL and isn't a secret. | +| **API Key ID** and **API Key Secret** | Zendesk | Send outbound messages through HTTP Basic authentication. | +| **Webhook Secret** | You | Optional. When set, every request must carry `x-api-key` with the lowercase hex HMAC-SHA256 of the untouched raw body. | +| **Webhook URL** | Artemis | Receives events at `/api/v1/channels/zendesk/webhook/{appId}`. The generic `/zendesk/webhook` path can't select a connection. | -The App ID travels in a public URL and isn't a secret. It exists for deterministic lookup, so authorization rests on the API key and on whatever verification you put in front of the endpoint. +Artemis keys each session to the app and the conversation, and posts replies to `/v2/apps/{appId}/conversations/{conversationId}/messages`. --- -## Zendesk setup - -Complete the tab that matches your Zendesk account. Both paths produce the same three values: the App ID, the API Key ID, and the API Key Secret. - - - - Use this path if your messaging runs on Zendesk Suite. Zendesk's [Conversations API keys article](https://support.zendesk.com/hc/en-us/articles/4576088682266-Using-the-Conversations-API-keys) covers the same screen. - - - - 1. Open Admin Center and select **Apps and integrations** in the sidebar. - 2. Select **APIs** -> **Conversations API**. - - If the page doesn't appear, your plan or workspace configuration is the cause rather than a permissions problem. The page needs Zendesk Suite Professional or above with Agent Workspace activated. - - - - 1. Click **Create API key**. - 2. Enter an identifying name for the key, then click **Next**. - 3. Copy the **App ID**, **Key ID**, and **Secret** from the panel Zendesk shows. - - Zendesk displays the secret once. Copy all three values into your secret manager before you close the panel, because recovering the secret means creating a replacement key. - - Create a dedicated key for this Artemis connection rather than reusing one that already serves another integration. An account stores up to 10 keys, so a separate key per integration costs nothing and lets you revoke this one in isolation. - - - - Check that the app already carries a channel a customer can message, such as the Web Widget or a connected social channel. - - Artemis attaches to an existing app rather than creating an entry point. Without a connected channel, the webhook registers correctly and no customer can ever reach it. - - - - - - Use this path if your account holds a separate Sunshine Conversations license rather than the one bundled with Zendesk Suite. - - - - Sign in to the Sunshine Conversations dashboard and select the app that owns the customer-facing integration, or create one. +## Prepare the Sunshine Conversations app - Keep development and production on separate apps. An app aggregates every channel it serves, so sharing one mixes test conversations into customer history. - +Do this in Zendesk before you open Artemis. Select **Open Sunshine Conversations** or **Open API documentation** in the setup guide to jump straight there. - - Open the app's settings and copy the app-level identifier. + + + Sign in to the Sunshine Conversations dashboard, or in Admin Center go to **Apps and integrations** -> **APIs** -> **Conversations API**. Choose the app that owns the customer-facing integration. Keep development and production apps separate. + - Sunshine Conversations surfaces several identifiers that look similar. Don't substitute a Zendesk subdomain, an integration ID, a conversation ID, a user ID, a webhook ID, or the API key ID. The App ID identifies the app itself and never changes. - + + Copy the app-level identifier from the app settings. Don't use a Zendesk subdomain, integration ID, conversation ID, user ID, webhook ID, or API key ID. + - - 1. Open the **Settings** tab, then find the **API keys** section. - 2. Create a key for this Artemis connection. - 3. Copy both the **Key ID** and the **Key Secret** while the secret is still visible. + + Open the app's **API keys** settings and create a key for this connection. Copy both the Key ID and the Key Secret while the secret is visible, because Zendesk shows it once. + - These two values authorize outbound messages for every conversation in the app, so treat the secret as a high-value credential and store it only in your secret manager. - - - - + + The app needs a supported Sunshine Conversations integration or client, such as the Web Widget, through which a customer can start a conversation. The Artemis webhook doesn't create one. + + --- ## Artemis channel configuration -Create the connection before you register the webhook. The callback URL ends with the App ID, and Artemis can resolve inbound events only after an active connection exists. +Create the connection before Zendesk sends webhooks. Artemis resolves webhooks only for an active connection. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **Zendesk** -> **+ New**. -3. Configure the following fields: - - | Artemis connection field | Source / Notes | - |---|---| - | Display Name | The label operators see in the connections list. Name it for the app and the environment it serves, because a project can hold several Zendesk connections. Routing ignores this value. | - | App ID (identifier) | The routing key. Artemis writes it into the webhook path and selects the connection from it. Enter the exact Sunshine Conversations App ID. | - | App ID (credential) | The same value again, used for provider operations. A mismatch between the two can accept one app's inbound route and then fail or misdirect the outbound reply. | - | API Key ID | The username half of the Basic credential for outbound messages. From the same app as the App ID. | - | API Key Secret | The password half. Zendesk shows it once at key creation. | - | Webhook Secret | Optional. Set it only when something in front of Artemis can add the matching `x-api-key` HMAC header. Leave it empty otherwise, or every inbound event fails. | - | Environment | The published environment whose active deployment answers incoming messages. Leave the working copy default only while you develop. | - | Provider Verification Strength | How far Artemis trusts Zendesk's identity assertion when it links a customer to an existing session. **Weak** suits most deployments. Choose **Strong** only when you trust those assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Whether the connection starts handling messages. Set it to **Active**, because Artemis resolves inbound webhooks only for an active connection. | - -4. Click **Create**. -5. Open the connection and copy the **Webhook URL** from the **Overview** tab.
- The URL ends with the App ID. Copy the whole thing, because the generic Zendesk webhook path can't identify which connection an event belongs to. - -### Validation checklist - -| Validation item | Expected result | -|:---|:---| -| Select the Sunshine Conversations app | App identified, with at least one customer channel already connected to it. | -| Copy the App ID | App-level identifier copied, distinct from subdomain, integration, conversation, user, webhook, and key IDs. | -| Create the API key | Key ID and Key Secret copied and stored while the secret was visible. | -| Create the Artemis connection | Connection saved as Active, with the same App ID in both the identifier and credential fields. | -| Copy the webhook URL | Webhook URL copied from the **Overview** tab, ending with the App ID. | -| Register the integration | Conversations integration created in the same app, targeting that URL. | -| Subscribe the triggers | `conversation:message` subscribed, plus `conversation:postback` if the agent sends buttons. | -| Bind a deployment | The connection's **Deployment** tab shows a runnable active deployment. | -| Send a real message | Test conversation reaches the agent and one reply appears. See [Verify the connection](#verify-the-connection). | +2. Go to **Deployments** -> **Channels** -> **Zendesk** -> **+ New**. The **New Zendesk Connection** dialog opens, with the setup guide on the left and the fields on the right. +3. Configure the fields: + + | Artemis field | Source / Notes | What it controls | + |---|---|---| + | **Display Name** | You choose it | The label operators see. Name it for the app and environment. Routing ignores it. | + | **App ID** (identifier) | App settings | The routing key, used in the webhook path to select the connection. | + | **App ID** (credential) | The same App ID | Used for provider operations. A mismatch can accept one app's route but fail or misdirect replies. | + | **API Key ID** | The app's API key | The username for outbound HTTP Basic authentication. | + | **API Key Secret** | The app's API key | The password for outbound HTTP Basic authentication. | + | **Webhook Secret** (optional) | You create it | Requires the `x-api-key` HMAC on every request. Leave it empty unless a sender or trusted middleware generates that header. | + | **Environment** | Your published environments | The environment whose active deployment answers messages. Leave the working copy default only while you develop. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts Zendesk's identity assertion when it links a customer to an existing session. Choose **Strong** only when you base continuity and account-linking decisions on it. | + | **Initial Status** | Defaults to **Active** | Keep it **Active** for immediate use. | + + Artemis asks for the App ID twice, once as the routing identifier and once as an encrypted credential. Paste the same value into both. + +4. Select **Create**. +5. Copy the **Webhook URL** from the connection's summary panel. It ends with the encoded App ID. --- -## Webhook configuration in Zendesk - -Zendesk calls the webhook a conversations integration in Admin Center, and a webhook in the Sunshine Conversations dashboard. Both create the same object. Zendesk documents the Admin Center route in [Creating conversations integrations in Admin Center](https://support.zendesk.com/hc/en-us/articles/4576083789850-Creating-conversations-integrations-in-Admin-Center). - - - - In Admin Center, select **Apps and integrations** in the sidebar, then **Integrations** -> **Conversations integrations**, and click **Create integration**. - - In the Sunshine Conversations dashboard, add a webhook from the app's integrations area instead. Create it in the same app that issued your API key, because a webhook registered on a neighboring app delivers events that this connection can't claim. - +## Register the webhook - - Paste the complete **Webhook URL** from the connection's **Overview** tab, including the App ID segment at the end. +Register the webhook in the same Sunshine Conversations app as the credentials. In Admin Center, go to **Apps and integrations** -> **Integrations** -> **Conversations integrations** and select **Create integration**. - Zendesk sends an HTTP HEAD request to the root domain when you save, checking that the domain resolves and a service answers. A save that fails at this point signals a reachability issue, not a problem with the path. - +1. Confirm the Artemis connection exists and is **Active**. +2. Paste the full App-ID-specific URL. Use the public HTTPS Runtime origin, and keep the final encoded App ID segment. +3. Subscribe to `conversation:message` for customer text, and `conversation:postback` for reply-button actions. Artemis ignores unsupported event types. +4. Save the webhook and keep it enabled. Confirm deliveries reach Artemis with a 2xx response, and keep event IDs stable for retry deduplication. +5. If you set **Webhook Secret**, make sure every request carries the matching `x-api-key` HMAC of the untouched raw body. With the field blank, Artemis accepts inbound events without a signature. - - Select **Conversation message** to receive customer text, which Zendesk sends as `conversation:message`. +Don't paste the API Key Secret into **Webhook Secret**. Configure a separate shared value only when the sender or middleware generates the `x-api-key` HMAC exactly as Artemis expects. - Add the postback trigger as well if your agent sends buttons. Postback taps arrive as `conversation:postback` rather than as messages, so an agent with buttons and no postback subscription answers text and then goes silent when someone taps. Artemis ignores event types it doesn't support, so extra triggers cause no harm beyond noise. - +### Validation checklist - - Save the integration, then check the delivery history after your first test to confirm Zendesk receives a 2xx response. +Work down this list once per connection. - Preserve the event identifiers Zendesk sends. Artemis deduplicates on the first event ID, so middleware that rewrites identifiers turns a provider retry into a duplicate agent turn. - - +| Validation item | Expected result | +|:---|:---| +| Prepare the app | App ID, Key ID, and Key Secret from one app, with a customer integration connected. | +| Create the Artemis connection | Saved as **Active**, with the same App ID in both fields. | +| Register the webhook | Same app, full App-ID URL, and both triggers subscribed. | +| Test a conversation | One customer message produces one agent reply. | --- ## Verify the connection -Artemis doesn't synthesize Zendesk events, so a real conversation through a connected channel is the only end-to-end proof. +Artemis doesn't synthesize Zendesk events, so a real conversation is the only end-to-end proof. -1. From the app's connected customer channel, send a short message you can search for later.
- Use the actual customer client rather than an agent-side tool, because the two produce different author types. -2. Confirm one `conversation:message` delivery, one Artemis session, and one agent turn. -3. Check that the reply appears in the same customer conversation.
- Artemis posts it as a business author through the Sunshine Conversations API, so the reply shows as coming from the business rather than from an agent. -4. Send an authored response carrying a button, tap it in the customer client, and confirm the postback resumes the same conversation with the action value you authored. -5. Confirm the agent's own reply doesn't trigger a second turn.
- Artemis ignores business-authored message events by design. A loop here means middleware is rewriting agent messages as customer or user authors. +1. From the app's connected customer client, send a unique message. Confirm one `conversation:message` delivery, one session keyed by app and conversation, and one agent turn. +2. Confirm Artemis posts the reply to `/v2/apps/{appId}/conversations/{conversationId}/messages` as a business author, and that it appears in the same conversation. +3. Send an authored response with a button, select it in the customer client, and confirm `conversation:postback` resumes the same conversation with the expected action value. +4. Confirm the agent's reply doesn't create a second turn. Artemis ignores business-authored `conversation:message` events by design. --- ## Message behavior and limits -Sunshine Conversations normalizes many channels into one API, which shapes what your agent can rely on. +Sunshine Conversations normalizes many channels into one API. | Area | Behavior | -| ---- | -------- | -| Channel coverage | The connection inherits every channel the app serves. A reply that renders well in the Web Widget may fall back to plain text on SMS, so author for the least capable channel your app carries. | -| Buttons | Zendesk falls back automatically where a channel lacks native buttons, for example rendering a link button as a hyperlink. Test the fallback rather than assuming the authored form. | -| Postbacks | Postback buttons stay tappable after use, so the same action can arrive more than once. Make your authored handling idempotent. | -| Author types | Artemis processes customer-authored events and ignores business-authored ones, which is what stops the agent answering itself. | -| Retries | Zendesk retries failed deliveries. Artemis deduplicates on the first event ID, so leave event identifiers untouched in transit. | -| Switchboard control | When a custom integration holds control of a conversation, Agent Workspace doesn't receive it, so messages appear without a ticket. Plan handoff explicitly if human agents need to take over. | +|---|---| +| Channel coverage | The connection inherits every channel the app serves. Author for the least capable channel. | +| Buttons | Zendesk falls back where a channel lacks native buttons. Test the fallback. | +| Author types | Artemis processes customer-authored events and ignores business-authored ones. | +| Retries | Artemis deduplicates on the first event ID. Preserve provider retries and don't rewrite event identifiers. | +| Switchboard control | When a custom integration holds the conversation, Agent Workspace doesn't receive it. Plan handoff if human agents take over. | --- -## Secure the connection - -The API key is the credential that matters here, and nothing protects the inbound side unless you add that protection yourself. - -The Key ID and Key Secret authorize the Sunshine Conversations REST API for every conversation in the app. Use a dedicated key for this connection, keep it in encrypted storage, redact it from diagnostics, and revoke keys you no longer use. Rotating the key means updating both halves in Artemis together, because Artemis sends them as one Basic credential. +## Security and lifecycle boundaries -Webhook verification is optional in this connection contract, and that's a deliberate trade rather than an oversight. With **Webhook Secret** empty, Artemis accepts inbound events without a signature. Setting it requires every request to carry an `x-api-key` header holding the lowercase hexadecimal HMAC-SHA256 of the untouched raw body, which Sunshine Conversations doesn't produce on its own. Put middleware in front of Artemis that generates the header exactly that way, or enforce an equivalent control at your ingress. +The API key is the credential that matters. The inbound side has protection only if you add it. -Don't paste the API Key Secret into **Webhook Secret**. Each secret protects a different direction of traffic, and reusing one value for both spreads a single compromise across inbound and outbound paths. - -Use distinct Sunshine Conversations apps or API keys, webhooks, secrets, and connections for development and production. +- **API key**: The Key ID and Key Secret authorize the Sunshine Conversations REST API. Use a dedicated key, encrypt it at rest, redact it from diagnostics, and revoke unused keys. +- **Webhook verification**: Optional in this connection. Production deployments should use the matching `x-api-key` HMAC path, or enforce an equivalent trusted ingress control. +- **App ID**: It appears in the public URL and isn't a secret. Authorization still depends on webhook verification and credential protection. +- **Environments**: Use distinct Sunshine Conversations apps or API keys, webhooks, secrets, and connections for development and production. --- ## Manage the channel connection -Opening a connection shows four tabs. The delete control sits beside the connection name. +Open a connection from **Deployments** -> **Channels** -> **Zendesk** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** reports the connection's state and identity. +**Header.** Shows the connection name, its status, and when it last changed. The **...** overflow menu holds the connection-level actions. - | Field | Description | - | ----- | ----------- | - | **Status** | Whether the connection currently handles messages. | - | **Created** and **Updated** | Date and time of creation, and of the last change. | - | **Environment** | The environment whose deployment answers messages. | - | **Source Type** | Reads `Channel Connection`. | - | **Source ID** | Identifies the connection uniquely. Quote it when you raise a support ticket. | - - **Setup Instructions** shows the **Webhook URL** to register in Zendesk and the **App ID** it ends with, each with a copy control. Compare the App ID here with the one in the payload whenever Artemis reports no connection found. - +**Summary panel.** Stays visible on every tab. +| Field | Description | +|---|---| +| **Channel** and **Connection Type** | Read **Zendesk** and **Channel Connection**. | +| **Identifier** | The App ID this connection routes on. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The App-ID-specific URL for Zendesk, with a copy control. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + + - Artemis encrypts credentials after you save them, so each field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new one to replace it. + Artemis encrypts credentials after you save them. Leave a field blank to keep its current value, or enter a new value to replace it. | Field | Description | - | ----- | ----------- | - | **Use Auth Profile** | Draws the credentials from a saved auth profile instead of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | **App ID** | The credential copy of the App ID. Keep it matched to the identifier, which you can read on the **Overview** tab. | - | **API Key ID** | Replace it when you issue a new key in Zendesk. | - | **API Key Secret** | Replace it alongside the Key ID, because Artemis sends the pair as one Basic credential. | - | **Webhook Secret** | Set or clear the optional HMAC requirement. Clearing it returns the endpoint to accepting unsigned events. | - - Click **Save Credentials** to apply your changes. + |---|---| + | **Use Auth Profile** | Turn it on, then select a saved auth profile in place of the fields below. | + | **App ID** | The credential copy. Keep it matched to the identifier. | + | **API Key ID** and **API Key Secret** | Replace both together when you issue a new key, because Artemis sends them as one Basic credential. | + | **Webhook Secret (optional)** | Set or clear the HMAC requirement. Clearing it accepts unsigned events. | + + Select **Save Credentials** to apply your changes. - Under **General**, rename the connection with **Display Name**, and revisit **Provider Verification Strength** if your trust posture for this app changes. - - Under **Zendesk Settings**, **App ID** appears read-only. The webhook URL is built from it, so changing it would invalidate the integration registered in Zendesk. Create a new connection to serve a different app. - - **Authorization Message** controls what the customer sees when a tool needs them to authorize something before the conversation continues. Write the template with these variables. - - | Scope | Variables | Use | - | ----- | --------- | --- | - | Message | `{{total}}`, `{{completed}}`, `{{remaining}}` | Summarize progress across every pending authorization, typically in a lead-in line above the list. | - | Repeat block | `{{#authorizations}}` and `{{/authorizations}}` | Wrap the section Artemis repeats once per pending authorization. | - | Item | `{{profileName}}`, `{{authLink}}`, `{{authUrl}}`, `{{index}}`, `{{count}}` | Identify and link each authorization inside the repeat block. | + Update how the connection behaves. **Zendesk Settings** holds the provider-specific fields. - Item variables resolve only inside the repeat block. Check the preview, and remember the message may render on a channel that strips formatting. + | Setting | Description | + |---|---| + | **Display Name** | The label operators see. | + | **Provider Verification Strength** | How far the runtime trusts Zendesk's identity assertion. | + | **App ID** | Read-only, with a copy control. To serve another app, create a new connection. | + | **Message template** | The authorization message the connection sends when a tool needs the user to authorize. Insert variables from the chips, select **Show more** for the full list, and select **Show preview** to check it. | + | **Webhook URL** | The App-ID-specific URL, with a copy control. | - Click **Save Changes** to apply your changes. + Select **Save Changes** to apply your changes. - Choose which deployed version of the agent answers messages on this connection. + Choose which deployed version answers Zendesk. - Under **Agent Version**, set **Environment** to the environment you want the connection to follow. **Active Deployment** then shows the version currently serving traffic. + | Setting | Description | + |---|---| + | **Environment** | Under **Environment Binding**. Selects which deployed version handles incoming messages. | + | **Active Deployment** | Shows the bound version and when someone deployed it. | - A connection left on the working copy shows a warning, because the working copy changes as you edit the agent. Bind the connection to a published environment before customers reach it. Click **Save Changes** after you switch. + A connection on **Working Copy (draft)** shows a warning, because the working copy is for testing. Deploy the agent to an environment and bind the channel to it before customers reach it. Select **Save Changes** after you switch the environment. @@ -290,34 +220,33 @@ Opening a connection shows four tabs. The delete control sits beside the connect ## Troubleshoot connection issues +Most failures trace to App ID mismatches, the API key, or the optional HMAC. + | Symptom | Likely cause | Recommended action | |---|---|---| -| The webhook returns connection not found | The URL doesn't carry the right App ID, or the connection isn't active | Confirm the URL ends with the exact App ID saved in Artemis, confirm the connection is Active, and confirm the payload's app identifier names the same app. | -| Outbound replies return 401 or 403 | The API key doesn't belong to the credential App ID, or someone revoked it | Verify the Key ID and Key Secret come from the same app as the credential App ID, and confirm nobody regenerated or revoked the key. | -| Customer messages never arrive | The integration sits on another app, the trigger isn't subscribed, or the endpoint isn't reachable | Confirm the integration lives in the same app as the credentials, subscribe `conversation:message`, confirm the endpoint answers over public HTTPS, and check Zendesk's delivery history for a 2xx. | -| Inbound processing works but no reply appears | The payload lacks a conversation reference, the credentials mismatch, or no deployment can run | Confirm the payload carries the conversation identifier, the app credentials match, the bound environment has a runnable deployment, and the Zendesk API is reachable. | -| The webhook returns 401 after you set Webhook Secret | Nothing is generating the expected header | Have your middleware set `x-api-key` to the lowercase hexadecimal HMAC-SHA256 of the untouched raw body, or clear the field for an intentionally unsigned deployment. | -| Replies create repeated turns | Something rewrites the author type | Inspect the event author type. Artemis ignores business authors, so a loop means middleware is presenting agent messages as customer or user authors. | -| Text works but buttons don't | The postback trigger isn't subscribed, or the channel can't render the action | Subscribe `conversation:postback`, confirm the customer channel supports reply actions, and confirm the authored action payload returns unchanged. | -| Messages appear in Zendesk but agents receive no ticket | Switchboard control sits with a custom integration rather than Agent Workspace | Check which integration holds control of the conversation, and pass control to Agent Workspace when a human agent needs to take over. | +| Connection not found | Wrong URL or inactive connection | Confirm the URL ends with the exact App ID saved in Artemis, the connection is **Active**, and the payload's `app.id` names the same app. | +| Outbound replies return `401` or `403` | API key mismatch or revoked | Confirm the Key ID and Key Secret belong to the credential App ID, and nobody regenerated or revoked them. | +| Customer messages don't arrive | Wrong app, missing trigger, or unreachable endpoint | Confirm you enabled the webhook in the same app, subscribed `conversation:message`, the public URL is reachable, and delivery history shows 2xx. | +| Inbound works but no reply appears | Missing conversation, credentials, or deployment | Confirm the payload includes `conversation.id`, the app credentials match, the environment can run, and the provider API is reachable. | +| Webhook returns `401` after you set Webhook Secret | No matching HMAC header | Preserve the raw request bytes and set `x-api-key` to the lowercase hex HMAC-SHA256 made with that secret, or clear the field for an intentionally unsigned deployment. | +| Replies create repeated turns | Author type rewritten | Inspect the event `author.type`. Artemis ignores business authors, so middleware must not rewrite agent messages as customer or user authors. | +| Text works but buttons don't | Missing postback trigger or channel support | Subscribe to `conversation:postback`, confirm the customer integration supports reply actions, and verify the action payload returns unchanged. | --- ## Zendesk reference -Use these Zendesk pages when you need detail beyond what this article covers. +Use these pages when you need detail beyond what this article covers. | Resource | Use it for | -| -------- | ---------- | -| [Using the Conversations API keys](https://support.zendesk.com/hc/en-us/articles/4576088682266-Using-the-Conversations-API-keys) | Creating and managing API keys in Admin Center, and the plan requirements. | -| [Creating conversations integrations in Admin Center](https://support.zendesk.com/hc/en-us/articles/4576083789850-Creating-conversations-integrations-in-Admin-Center) | Registering the webhook, viewing its IDs, and editing it later. | -| [API quickstart](https://developer.zendesk.com/documentation/conversations/getting-started/api-quickstart/) | Zendesk's own walkthrough of the webhook and the first reply. | -| [Receiving messages](https://developer.zendesk.com/documentation/conversations/messaging-platform/programmable-conversations/receiving-messages/) | Webhook payload structure, trigger list, and switchboard control. | -| [Structured messages](https://developer.zendesk.com/documentation/conversations/messaging-platform/programmable-conversations/structured-messages/) | Button types, postback behavior, and channel fallbacks. | -| [Creating and managing apps](https://docs.smooch.io/guide/creating-and-managing-apps/) | App-level concepts for accounts on a standalone Sunshine Conversations license. | +|---|---| +| [Using the Conversations API keys](https://support.zendesk.com/hc/en-us/articles/4576088682266-Using-the-Conversations-API-keys) | Creating API keys in Admin Center. | +| [Creating conversations integrations](https://support.zendesk.com/hc/en-us/articles/4576083789850-Creating-conversations-integrations-in-Admin-Center) | Registering the webhook. | +| [Receiving messages](https://developer.zendesk.com/documentation/conversations/messaging-platform/programmable-conversations/receiving-messages/) | Payload structure, triggers, and switchboard control. | +| [Structured messages](https://developer.zendesk.com/documentation/conversations/messaging-platform/programmable-conversations/structured-messages/) | Buttons, postbacks, and channel fallbacks. | {{related}} -- [Set up WhatsApp](/agent-platform/channels/whatsapp) -- [Set up Messenger](/agent-platform/channels/messenger) -- [Set up Twilio](/agent-platform/channels/twilio) \ No newline at end of file +- [Channels](/agent-platform/channels) +- [Set up Twilio SMS](/agent-platform/channels/twilio) +- [Set up Genesys](/agent-platform/channels/genesys) \ No newline at end of file From 2474c567b9d40386980261f9c0022bd98d79a18e Mon Sep 17 00:00:00 2001 From: Prabhat Singh <109069787+prabhat-singh-kore@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:45:05 +0530 Subject: [PATCH 3/4] Parallel and Sequential Tool Execution explanation in tools-overview, workflows.mdx and ABL > tools.mdx Parallel and Sequential Tool Execution explanation in tools-overview, workflows.mdx and ABL > tools.mdx --- agent-platform/abl/reference/tools.mdx | 34 ++++++++++++++++++++++++++ agent-platform/tools-overview.mdx | 4 +++ agent-platform/workflows.mdx | 21 +++++++++++++--- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/agent-platform/abl/reference/tools.mdx b/agent-platform/abl/reference/tools.mdx index 2307247d5..52fbfd203 100644 --- a/agent-platform/abl/reference/tools.mdx +++ b/agent-platform/abl/reference/tools.mdx @@ -1148,6 +1148,40 @@ TOOLS: When neither `effect` nor `hints.side_effects` is declared, the runtime infers one: for an HTTP tool, `GET`, `HEAD`, and `OPTIONS` default to read-only and every other method defaults to side-effecting; SearchAI and read-only table bindings default to read-only; any other non-HTTP tool defaults conservatively to side-effecting. An explicit `effect`/`side_effects` always wins over the inferred default. +### Concurrent tool execution + + +A reasoning agent works in steps. At each step, the model chooses which tools to call. When it requests more than one tool in the same step, the platform runs them at the same time. A tool whose arguments depend on another tool's result can't be requested until that result exists, so it is naturally called in a later step. + +```yaml +TOOLS: + get_profile(customer_id: string) -> {name: string, tier: string} + description: "Fetch the customer profile" + effect: read_only + + get_orders(customer_id: string) -> {last_order_id: string, orders: array} + description: "Fetch recent orders" + effect: read_only + + get_delivery_status(order_id: string) -> {status: string, eta: string} + description: "Get delivery status for one order" + effect: read_only + +INSTRUCTIONS: | + For an account and order update: + 1. Call get_profile and get_orders together in the same step. + 2. When get_orders returns, call get_delivery_status with its last_order_id. + 3. Then answer using all three results. +``` + +`effect: read_only` marks a tool as a pure lookup. A read-only tool executes immediately: it is never held back while a separate call is waiting on customer [confirmation](#confirmation). + +The model decides which tools to request together, so `INSTRUCTIONS` is what makes the grouping consistent: tell it which calls are independent and can run together, and which call needs another call's result first. Instructions guide this grouping; they don't enforce it, since the model still chooses what to call at each step. For a fixed, guaranteed execution order, attach the calls as a [workflow tool](#workflow-tools) instead and define the order on the workflow canvas. See [Build workflow logic](/agent-platform/workflows#build-workflow-logic) for how nodes on the same branch run concurrently. + +This concurrency is automatic and needs no extra configuration. It's unrelated to a workflow tool's `mode` property (`sync` or `async`), which controls whether the calling agent waits for a long-running workflow run to finish, not whether multiple tool calls run together. + +To confirm which calls ran together, open the session trace: tool calls that ran at the same time show overlapping start and end times. + ### Result compaction diff --git a/agent-platform/tools-overview.mdx b/agent-platform/tools-overview.mdx index 70f22b3de..71f011aea 100644 --- a/agent-platform/tools-overview.mdx +++ b/agent-platform/tools-overview.mdx @@ -30,6 +30,8 @@ Use the Tools page to: For detailed configuration steps, see the documentation for each tool type. +When a reasoning agent requests more than one tool in the same step, the platform runs them at the same time; a tool that depends on another tool's result is called in a later step automatically. See [Concurrent tool execution](/agent-platform/abl/reference/tools#concurrent-tool-execution). + --- ## Workflow tools @@ -46,6 +48,8 @@ Workflow tools support: * Integration actions * Reusable business processes +Branches that start from the same workflow step run at the same time; a step with several incoming connections waits for all of them to finish before it runs. See [Build workflow logic](/agent-platform/workflows#build-workflow-logic). + For details about registering workflows as tools and attaching them to agents, see: * [Register workflows as tools](/agent-platform/workflows#register-workflow-as-a-tool) diff --git a/agent-platform/workflows.mdx b/agent-platform/workflows.mdx index c935df276..0cfd14fd9 100644 --- a/agent-platform/workflows.mdx +++ b/agent-platform/workflows.mdx @@ -118,9 +118,22 @@ Connect nodes visually on the canvas to define execution order. Workflows support: -* Sequential execution -* Conditional branching -* Parallel execution patterns +* Sequential execution: one node runs after another. +* Conditional branching: a [Condition node](#condition-node) routes to different next nodes. +* Parallel execution: nodes connected from the same parent node run at the same time. + +Nodes connected from the same parent node run concurrently. For example, two Tool nodes that both connect directly from the Start node start at the same time. A node with several incoming connections waits for all of them to finish before it runs. + +```text +Start ─┬─► Get_Profile ──────────────────────┐ + └─► Get_Orders ─► Get_Delivery_Status ─┴─► End +``` + +In this example, `Get_Profile` and `Get_Orders` both run as soon as the workflow starts. `Get_Delivery_Status` needs the order ID that `Get_Orders` returns, so it waits for `Get_Orders` and runs only after it finishes. `End` has two incoming connections (`Get_Profile` and `Get_Delivery_Status`), so it waits for both to finish before it runs. + +Model independent calls as separate branches from the same parent node to run them concurrently. Model a dependent call as a node downstream of the call it needs. Use each node's Test Action to confirm the exact output path before wiring the next node to it. + +A workflow's branches always run in the connections you draw, every run. This is different from a reasoning agent's own tool calls, where the model chooses what to request at each step. See [Concurrent tool execution](/agent-platform/abl/reference/tools#concurrent-tool-execution) for how that works and when to use it instead of a workflow. ### Use workflow variables @@ -708,6 +721,8 @@ Attached workflows allow agents to execute workflow logic during conversations a 5. Select the trigger and execution mode (sync or async). 6. Click **Register Workflow**. +In `sync` mode, the agent waits for the workflow run to finish and gets the End node's output back as the tool result. In `async` mode, the tool call returns a handle right away and the workflow keeps running. See [Workflow binding properties](/agent-platform/abl/reference/tools#workflow-binding-properties) for the underlying `mode` and `timeout_ms` settings. + ### Workflow tool definition After a workflow is registered, it can be attached to agents as a workflow tool. From a2c49651b7618a2f203b33105a65934ea5fe0050 Mon Sep 17 00:00:00 2001 From: siddharthmenon-7 Date: Thu, 22 Oct 2026 19:48:37 +0530 Subject: [PATCH 4/4] Fixed link --- agent-platform/channels/slack.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent-platform/channels/slack.mdx b/agent-platform/channels/slack.mdx index a48023bf9..0a89689a0 100644 --- a/agent-platform/channels/slack.mdx +++ b/agent-platform/channels/slack.mdx @@ -287,5 +287,5 @@ Use these pages when you need detail beyond what this article covers. {{related}} - [Channels](/agent-platform/channels) -- [Set up Microsoft Teams](/agent-platform/channels/microsoft-teams) +- [Set up Microsoft Teams](/agent-platform/channels/ms-teams-copilot) - [Set up WhatsApp](/agent-platform/channels/whatsapp) \ No newline at end of file