diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index b7584e7ee..59bcb19ed 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -11,6 +11,8 @@ */ "MD001": true, //Heading levels should only increment by one level at a time. But in RNs we use this. + "MD009": true, //No trailing spaces. + "MD012": true //Multiple consecutive blank lines. "MD013": false, //Line length should be within limits. "MD022": true, //Headings should be surrounded by blank lines "MD023": true, //Headings must start at the beginning of the line @@ -19,12 +21,15 @@ "MD029": true, //Ordered list item prefix. Turn to true later since it'll catch improperly-indented content in ordered lists. "MD031": true, //Fenced code blocks should be surrounded by blank lines. Turn to true later. "MD032": true, //Lists should be surrounded by blank lines + "MD033": false, //No inline HTML "MD034": true, //Bare URL or email used. Mentions of naked email ID converts an intended sample to a mailto link. Or a sip example to a mailto link. "MD036": false, //Emphasis used instead of a heading. We use bold for heading but that's incorrect. "MD039": true, //Spaces inside link text. Turn it on later "MD040": true, //Fenced code blocks should have a language specified. + "MD041": true, //All articles start with a heading in the first line in the MD file. + "MD047": true, //Files should end with a single newline character "MD056": true, //Table column count. Some incorrectly-formatted table rows can have less or more cells than the rest of the table. The information in such cells is lost in the output that we don't want. "MD058": true, //Tables should be surrounded by blank lines. "MD059": true, //Link text should be descriptive. Turn it on later after we edit link texts. - "MD041": true //All articles start with a heading in the first line in the MD file. + "MD060": false //Table column style } diff --git a/README.md b/README.md index f2ffb4172..beff97212 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,11 @@ Other business solutions of Kore.ai: ## Contribute to this Documentation -Prerequisites to author and contribute are: +This repo is public. To contribute edits, clone it or fork it and submit a PR. Request a review of your PR and wait for it to be merged to `main`. To report bugs or share suggestions, create an issue. -- [Node.js](https://nodejs.org) v20.17.0 or later (LTS version recommended). -- Get write access to this repo. -- Install Mintlify CLI `npm i -g mintlify`. +When editing .mdx files, follow GitHub Flavored Markdown syntax. -To author and preview, follow these steps: - -1. Clone the repo. Use GitHub Desktop client. -1. Work only in your [product-specific branch](https://github.com/Koredotcom/docs-v2/branches) and your product-specific folder. -1. Create or update the .mdx files or other assets. -1. To preview locally, create a local build using `mint dev` or `mint dev --port xxxx` in the cloned repo's root folder. -1. To preview on stage, create [a pull requests](https://github.com/Koredotcom/docs-v2/pulls) targeting `main` branch and view the preview or deployment link in it. -1. To publish your doc updates, request a review of your PR and wait for it to be merged. Do NOT merge on your own. +To preview your edits locally, use the npm package of [Mintlify](https://www.mintlify.com/docs/cli/index). ## Folder structure and common files @@ -45,12 +36,17 @@ assets/ # Common assets for all docs, say favicon, logo, etc. Used in d ├── koreailogo-white.svg custom-css # custom stylesheets. Don't edit. ├── style.css +drafts # Drafted content or assets that are to be used later. snippets # Reusable content for single sourcing .cspell.json # Spell check config file that's NOT available in the repo but added in everyone's local clone manually. Works when extension is installed in VSCode editor. .gitignore # Exclusions from repo uploads +.lycheeignore # Configuration for Lychee linkchecker. It is configured to run as an on-demand Action on this repo. .markdownlint.jsonc # Markdown linting rules. Works when extension is installed in VSCode editor .mintignore # Exclusions from the Mintlify build docs.json # Config, TOC, home page design theme, analytics integration, etc. home.mdx # Docs home page License # MIT license for docs +linkinator.config.json # Config for Linkinator link checker. It is used separately from the CLI. +README.md # This file. +search.js # JavaScript that powers search of AI for Service and AI for Work help articles. ``` diff --git a/agent-platform/abl/reference/configuration-reference.mdx b/agent-platform/abl/reference/configuration-reference.mdx new file mode 100644 index 000000000..725a84899 --- /dev/null +++ b/agent-platform/abl/reference/configuration-reference.mdx @@ -0,0 +1,53 @@ +--- +title: Configuration reference +sidebarTitle: Configuration reference +--- + +A one-page index of every setting that changes what the model reads on a turn -- where it's set, what it defaults to, and what it changes. Use this page to find the right lever quickly, then follow the link to the full reference for the syntax and examples. + +ABL settings take effect in new conversations once saved, or once published and deployed for production channels. Project settings take effect on the next turn unless noted otherwise. + +Knowledge-base and voice levers are covered in full on [Knowledge bases and knowledge tools](/agent-platform/knowledge) and [Voice agents](/agent-platform/channels/voice) -- this table includes only their headline entries. + +| Setting | Where | Default | Changes | +|---------|-------|---------|---------| +| [`BEHAVIOR: role:`](/agent-platform/abl-reference/multi-agent-and-supervisor#behavior-settings) | Agent ABL | Not set (allow-list mode) | Which values reach `## Current Context`, and which prompt template is used -- see [How a turn is built](/agent-platform/context-and-prompts#what-the-model-sees-each-turn) | +| `GOAL`, `PERSONA`, `LIMITATIONS`, `{{refs}}` | Agent ABL | -- | The identity section; references also make values visible in `## Current Context` | +| `SYSTEM_PROMPT:` | Agent ABL | Catalog template | Replaces the template; runtime sections are still appended | +| [`MEMORY: SESSION:`](/agent-platform/memory-and-state#session-memory) | Agent ABL | -- | `## Session Memory` content, and what the model may write | +| [`MEMORY: persistent:`, `remember:`, `recall:`](/agent-platform/memory-and-state#persistent-memory) | Agent ABL | -- | Values loaded into the session; `recall: INSTRUCTION` lines in the prompt | +| [`HANDOFF … CONTEXT:`](/agent-platform/abl-reference/multi-agent-and-supervisor#handoff-context) (`pass`, `summary`, `history`, `memory_grants`) | Agent ABL | `history: full` | The receiving agent's history, context, and granted memory | +| [`DELEGATE … INPUT` / `PURPOSE`](/agent-platform/abl-reference/multi-agent-and-supervisor#delegate) | Agent ABL | -- | The only context a delegate gets | +| `CONVERSATION:` | Agent ABL | -- | `## Conversation Behavior` lines; listening and barge-in behavior on voice | +| [`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.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 | +| [Tool `compaction:`](/agent-platform/abl-reference/tools#result-compaction) (`essential_fields`, `summary_timeout_ms`, `max_search_tokens`) | Tool ABL | -- | Per-tool compaction, and the knowledge-base token budget | +| [Tool `store_result`](/agent-platform/abl-reference/tools#store-result) | Tool ABL | `true`; `false` once the tool has `on_result: SET` | Whether `last__result` is kept | +| Tool param `default_source`, `visibility_model`, `visibility_trace` | Tool ABL | Visible | Hides a runtime-supplied value from the model and from traces | +| [KB `search_instructions`, `kb_name`, `description`](/agent-platform/knowledge#tool-level-search-settings) | Tool ABL / KB settings | -- | How and when the model searches | +| [Index Top K, similarity threshold, keyword weight](/agent-platform/knowledge#additional-settings) | Studio KB index settings | 10, 0.2, 0.5 | How many chunks come back | +| Citations | Studio KB citation settings | On by default, per index | Citation instructions added to the prompt | +| [`GUARDRAILS:`](/agent-platform/abl-reference/guardrails) | Agent ABL | -- | Per-agent checks -- see [Guardrail checkpoints](/agent-platform/safety-and-guardrails#guardrail-checkpoints) | +| Guardrail policies, providers, fail mode | Studio Govern → Guardrails | Fail open | Project and tenant checks; `## Current Policy` | +| [Project compaction](/agent-platform/context-compaction#where-to-set-compaction-policies) | Project runtime config (API or import) | Platform defaults | Project-wide budgets; resolved once per conversation | +| [Voice latency profile and overrides](/agent-platform/administration/general-settings#voice-low-latency-profile) | Studio Settings → Runtime Config | Auto-seeded for voice | Tighter budgets, fast model tier, reasoning off, inline gather on | +| Filler | Project runtime config | Profile defaults | Voice filler behavior and the status-update instruction | +| [PII redaction](/agent-platform/administration/general-settings#pii-redaction) (`pii_redaction`) | Project runtime config | On | Tokens in place of personal data in the prompt and in traces. Built-in detectors start off on new projects. | +| [Multi-intent](/agent-platform/administration/general-settings#multi-intent-recognition) | Project runtime config | -- | Multi-request routing and task sections | +| [Cross-channel recall](/agent-platform/administration/agent-behavior-settings#omnichannel) | Project omnichannel settings | Per project | `## Previous Conversations (Other Channels)`: up to 30 messages of 500 characters each | + +Fixed by the platform, not configurable: the order of prompt sections, the Customer Output Contract, the tool-history marker and its 6-round window, the realtime voice handoff history-replay limits, and the absolute limits on `## Current Context` (40,000 characters per value, 100,000 for the whole block). + +--- + +{{related}} + +- [How a turn is built](/agent-platform/context-and-prompts) -- what each of these settings ultimately controls. +- [Context size, compaction, and budgets](/agent-platform/context-compaction) -- the compaction defaults in full. +- [Agent declaration](/agent-platform/abl-reference/agent-declaration) -- `GOAL`/`PERSONA`/`SYSTEM_PROMPT` and the `EXECUTION:` block. +- [Multi-agent and supervisor](/agent-platform/abl-reference/multi-agent-and-supervisor) -- `HANDOFF`, `DELEGATE`, and `ESCALATE`. diff --git a/agent-platform/abl/reference/multi-agent-and-supervisor.mdx b/agent-platform/abl/reference/multi-agent-and-supervisor.mdx index 5e326f38d..bf65ee388 100644 --- a/agent-platform/abl/reference/multi-agent-and-supervisor.mdx +++ b/agent-platform/abl/reference/multi-agent-and-supervisor.mdx @@ -481,6 +481,8 @@ CONTEXT: The legacy shorthand `history: last_10` is still accepted during the compatibility window, but new agents should use the typed `mode` + `count` block. +Three forms parse without error and are silently ignored, each falling back to `full`: a single-line flow-mapping value such as `history: { mode: last_n, count: 3 }` (use the indented block shown above instead); an uppercase key inside `CONTEXT:`, such as `HISTORY:` or `PASS:` (keys inside `CONTEXT:` must be lowercase, unlike the handoff entry's own `TO:` / `WHEN:` keys); and a misspelled value, such as `history: recent`. Check the Request view of the target agent's first LLM step (see [LLM step request and response](/agent-platform/sessions#llm-step-request-and-response)) if the history you expect isn't showing up. + ### Return expectations When `EXPECT_RETURN: true`, the calling agent pauses and waits for the target agent to complete. diff --git a/agent-platform/abl/reference/tools.mdx b/agent-platform/abl/reference/tools.mdx index 93d8acc30..2307247d5 100644 --- a/agent-platform/abl/reference/tools.mdx +++ b/agent-platform/abl/reference/tools.mdx @@ -1313,6 +1313,12 @@ TOOLS: store_result: false ``` +When `store_result` is `true` (the default), the raw result is kept as a session value named `last__result`. It surfaces in `## Current Context` on later turns, but only for the agent that called the tool, and cut to 4,000 characters. This is separate from the within-turn shaping in [Result compaction](#result-compaction) and [MODEL_CONTEXT on a tool result](#model_context-on-a-tool-result) above, which apply only while the call is in progress -- `last__result` is what carries the result forward once the turn ends. + +Declaring an `on_result: SET:` block on the tool changes the default: `store_result` becomes `false` and `last__result` is no longer written, unless `store_result: true` is set explicitly alongside it. If a later turn needs a field from the result, either keep `store_result: true` or capture that field into a session value with `on_result: SET:`. + +For the agent-wide limits on how many compacted tool rounds survive in history, and how tool results are compacted across turns, see [Compaction policy overrides](/agent-platform/abl-reference/agent-declaration#compaction-policy-overrides). + ### Reuse secrets across tools (SecretRef) Some flows need a credential produced by one tool (a one-time token, session key, or OTP) to be sent to a later tool — without ever exposing the raw value to the LLM. SecretRef captures such values into an encrypted, session-scoped **secret vault** and restores them into downstream tool calls. diff --git a/agent-platform/administration/agent-behavior-settings.mdx b/agent-platform/administration/agent-behavior-settings.mdx index 7fd4a6977..fce829f92 100644 --- a/agent-platform/administration/agent-behavior-settings.mdx +++ b/agent-platform/administration/agent-behavior-settings.mdx @@ -251,6 +251,8 @@ The **Agent Transfer Settings** page configures defaults for agent transfer sess **Navigation**: **Project** → **Settings** → **Agent Transfer** +These are project-wide defaults for a human-agent transfer. An agent overrides them at runtime with an `ESCALATE` block's `routing` and `routing.voice` -- see [Routing configuration](/agent-platform/abl-reference/multi-agent-and-supervisor#routing-configuration) and [Voice transfer settings](/agent-platform/abl-reference/multi-agent-and-supervisor#voice-transfer-settings) in the ABL reference. + The page organizes content into three collapsible sections. Select a section header to expand or collapse it. Select **Save** to apply changes or **Reset** to restore all values to defaults. | Section | Description | diff --git a/agent-platform/administration/ai-configuration.mdx b/agent-platform/administration/ai-configuration.mdx index bf27970b6..0d01a6996 100644 --- a/agent-platform/administration/ai-configuration.mdx +++ b/agent-platform/administration/ai-configuration.mdx @@ -20,7 +20,9 @@ The Agent Platform is provider-neutral. Agents can use models from multiple LLM The page is organized into three tabs: **Credentials**, **Model Catalog**, and **Project Access**. -{/*### How model resolution works +{/* + +### How model resolution works Model configuration follows a layered approach. When the runtime executes an agent, it resolves the model through a five-level priority cascade, stopping at the first match: @@ -53,6 +55,7 @@ Every LLM call tracks token usage and estimated cost, broken down by agent, proj | Estimated cost | Calculated from token counts and the model's known pricing. | | Model used | Which model served the request. | | Latency | Time-to-first-token and total request duration. | + */} ### Credentials diff --git a/agent-platform/administration/general-settings.mdx b/agent-platform/administration/general-settings.mdx index 283325b84..959842c56 100644 --- a/agent-platform/administration/general-settings.mdx +++ b/agent-platform/administration/general-settings.mdx @@ -675,6 +675,8 @@ This section controls how the runtime handles personally identifiable informatio | **Classify explicit DTMF using project PII patterns** | Matches a completed keypad entry to the project's enabled PII patterns, so a recognized value carries a type and a validation status while anything else stays a generic token. Raw digits never reach the model either way, so this setting changes how an entry is labelled rather than whether it's protected. | | **Detection methods allowed** | Sets the ceiling on which detection engines the project's patterns may use. Each pattern still selects its own method on the PII Protection page, so this field decides what's available to them rather than what they do. | +This redaction policy is project-wide. For a specific tool that needs to see the original, unredacted values despite it, see [PII access](/agent-platform/abl-reference/tools#pii-access) (`pii_access`) in the ABL tools reference. + ### Lookup tables Lookup tables are the reference data the runtime uses to validate field values and perform fuzzy matching during extraction. diff --git a/agent-platform/administration/integrations-settings.mdx b/agent-platform/administration/integrations-settings.mdx index aa827de85..e3f692d00 100644 --- a/agent-platform/administration/integrations-settings.mdx +++ b/agent-platform/administration/integrations-settings.mdx @@ -17,13 +17,14 @@ Select **Connect Repository**, complete the fields, then select **Test connectio | Field | Description | |---|---| -| **Provider** | Selects the Git hosting service. It determines which credential types the **Auth Profile** picker accepts, so set it before you prepare a credential. | -| **Repository URL** | Points at the repository over HTTPS or SSH. It addresses the repository only. The folder this project occupies inside it comes from **Sync Path** further down. | -| **Repository Layout** | Decides whether this project shares a repository with others or takes one of its own. Choose a shared folder when you want every project's history in one place and one set of repository permissions. Choose a dedicated repository when a project needs its own access control or its own release cadence. | +| **Provider** | Selects the Git hosting service: **GitHub**, **GitLab**, **Bitbucket**, **Bitbucket Data Center**, or **Azure DevOps**. It determines which credential types the **Auth Profile** picker accepts and which repository URL forms the dialog takes, so set it before you prepare a credential. | +| **Repository URL** | Points at the repository over HTTPS or SSH. It addresses the repository only. The folder this project occupies inside it comes from **Sync Path** further down. Bitbucket Data Center accepts HTTPS only, in the `.../scm//.git` form. | +| **Repository Layout** | Decides whether this project shares a repository with others or takes one of its own. Choose a shared folder when you want every project's history in one place and one set of repository permissions. Choose a dedicated repository when a project needs its own access control or its own release cadence. A dedicated repository sets **Sync Path** to the repository root. | | **Branch** | Sets the branch the project reads and writes. Point non-production projects at a branch other than the one your builds run from, so an experiment in Studio doesn't reach it. | -| **Sync Path** | Sets the folder inside the repository that this project owns. Use the repository root when the project has the repository to itself, and a named folder when several projects share one. | +| **Sync Path** | Sets the folder inside the repository that this project owns. Use `/` for the repository root when the project has the repository to itself, and a named folder when several projects share one. With a shared folder, it defaults to `projects/`. | | **Path Preview** | Shows the location the platform resolved from your layout, path, and branch. Read it before you connect. It's the one place the three fields appear as the single destination they combine into. | -| **Auth Profile** | Selects the stored credential the sync uses. Select **Create Git token profile** to build one without leaving the dialog. | +| **Auth Profile** | Selects the stored credential the sync uses. The help text below the picker changes with the provider and names the profile types it accepts. Select **Create Git token profile** to build one without leaving the dialog. | +| **Require a project-owned auth profile** | Limits the integration to auth profiles this project owns, so workspace profiles can't serve it. Turn it on for production branches, so a change to a shared workspace profile can't affect this project's sync. | | **Conflict Strategy** | Decides what happens when Studio and the repository both change the same thing. Settle this before your first push rather than during your first conflict, since the strategy determines which side loses work. | ### Credentials by provider @@ -34,10 +35,21 @@ The picker lists only profile types that carry a token or key the sync can prese |---|---| | **GitHub** | A Bearer Token profile holding a personal access token, or an SSH Key profile. | | **GitLab** | A Bearer Token or API Key profile holding a project access token, or an SSH Key profile. OAuth Token grants don't appear here either. | -| **Bitbucket** | A raw repository or workspace access token, or an SSH Key profile. Atlassian API tokens need storing in the combined email and token form rather than as the token alone, which is the most common reason a valid Bitbucket credential fails. OAuth Token grants don't appear here either. | +| **Bitbucket** | A Basic profile with your Atlassian account email as the username and a Bitbucket API token as the password. Grant the token read and write access to repositories and pull requests, and read, write, and delete access to webhooks. Enter the email and token in their own fields rather than combining them into one value. A repository or workspace access token, or an SSH Key profile, also works. OAuth Token grants don't appear here either. | +| **Bitbucket Data Center** | A Basic profile with your Bitbucket Data Center username as the username and a personal HTTP access token as the password. The token needs repository write permission, plus admin permission if you want Studio to register the webhook for you. SSH isn't supported for this provider. See [Connect Bitbucket Data Center](#connect-bitbucket-data-center). | | **Azure DevOps** | A Bearer Token or API Key profile holding an Azure DevOps personal access token. Grant it Code read and write, add Code manage if you want branch and pull request operations, and add a webhook subscription scope if you want automatic sync. SSH Key and OAuth profiles aren't supported for this provider at all, so plan on a token. | -Once the integration is live, you can push agent definitions, pull repository changes into Studio, and resolve conflicts when edits collide. +### Connect Bitbucket Data Center + +Bitbucket Data Center is the self-managed edition of Bitbucket. Studio syncs with it over HTTPS using native Git, and a few requirements differ from the cloud providers. + +| Requirement | Description | +|---|---| +| Repository URL | Use the HTTPS clone URL, which ends in `/scm//.git`. SSH URLs aren't accepted. | +| Auth profile | Use a Basic profile that holds your Data Center username and a personal HTTP access token with repository write permission. | +| Host consent | Studio asks you to allow the Data Center host to receive the profile's credentials before it connects. Consent applies to that host only, so a profile you allow for one server doesn't reach another. | +| Webhook | When the token carries admin permission, Studio registers the webhook for you. When it doesn't, Studio shows the webhook URL and a one-time secret instead, and a repository admin adds them in Bitbucket. Until someone adds the webhook, repository changes don't reach Studio automatically. | + --- ## Auth profiles diff --git a/agent-platform/channels/voice.mdx b/agent-platform/channels/voice.mdx index b8dd59f29..239ed7e74 100644 --- a/agent-platform/channels/voice.mdx +++ b/agent-platform/channels/voice.mdx @@ -5,323 +5,407 @@ title: Voice channels [Back to voice channels](/agent-platform/channels#voice-channels) ## Set up Realtime LLM Voice channel - -Supports live voice conversations using Realtime LLM models (OpenAI Realtime, Gemini Live) through the Kore.ai Voice Gateway or a Bring Your Own SIP connection. - -To configure a Realtime LLM Voice channel, go to **Deployments** > **Channels** > **VOICE** > **Realtime LLM Voice** > **+ New** and complete the following steps in order. - + +Realtime LLM Voice is a voice channel that handles live voice conversations through a single provider-native speech session. It supports Realtime LLM models (such as OpenAI Realtime and Gemini Live) through the Kore.ai Voice Gateway (KoreVG) or a Bring Your Own SIP connection. + +Unlike the STT → LLM → TTS pipeline that Pipeline Voice uses, a provider-native realtime model owns the live audio conversation. KoreVG handles telephony, connection routing, bounded session state, traces, and the call lifecycle. + +Studio also provides in-product guidance. On the **Realtime LLM Voice** channel page, click **Setup instructions** to open a step-by-step panel that covers connection creation, provider and phone routing, call quality validation, and security, latency, and reliability boundaries. + +### Create a Realtime LLM Voice channel + +To create a Realtime LLM Voice channel, go to **Deployments** > **Channels** > **Voice** > **Realtime LLM Voice** > **New connection** and complete the following steps in order. + - + On the **New Realtime LLM Voice Connection** page, provide the following fields. - - | Field | Description | - | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | **Display Name** | A label for the connection. | - | **Connection Name** | A system name for the connection, such as `realtime-voice-prod`. Up to 255 characters. | - | **Environment** | The deployment the connection binds to. Select an environment to follow its active deployment automatically, or leave the default to use the working copy. When no environment has an active deployment yet, create a deployment first to bind the connection to a published environment. | - | **Provider Verification Strength** | Controls how strictly the platform trusts the provider's identity assertions for session continuity and linking. **Weak** is the default. Choose **Strong** only for channels or providers whose identity assertions you trust. | - | **Initial Status** | **Active** connections are usable immediately. **Inactive** connections stay saved but disabled until you activate them. | - + | Field | Description | + | --- | --- | + | **Display Name** | A label for the connection. | + | **Connection Name** | A stable system name for the connection, up to 255 characters. Use an environment-specific identifier such as `realtime-voice-production`. It's an external identifier, not a phone number or a shared gateway account. | + | **Environment** | The deployment the connection binds to. Select an environment whose active deployment contains the realtime-compatible agent, tools, model policy, and welcome behavior. Select an environment to follow its active deployment automatically, or leave the default to use the working copy. When no environment has an active deployment yet, create a deployment first to bind the connection to a published environment. | + | **Provider Verification Strength** | Controls how strictly the platform trusts the provider's identity assertions for session continuity and linking. **Weak** is the default. Choose **Strong** only for channels or providers whose identity assertions you trust. | + | **Initial Status** | **Active** connections are usable immediately. **Inactive** connections stay saved but disabled until you activate them. Use **Inactive** while the provider and phone routing are incomplete. An **Active** phone-routed connection without a provisioned number can't receive production PSTN calls. | + + Click **Create**. + Create the connection before you configure voice details. The connection record must exist before Studio can provision a phone number and save provider-specific realtime settings. - - - After creating the channel, go to the **Configuration** tab. If you choose **Voice Provider: Kore.ai Voice Gateway**, set the following fields under **Kore.ai Voice Gateway**. - - | Route | Description | - | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | - | **Soft Phone** (FREE) | Dial the agent from your browser with no DID purchase or telephony charges. Use it for evals, QA, and demos. **Launch dialer** opens the browser dialer. | - | **Phone Number (DID)** | Purchase a real phone number through Twilio. Disable this route to stop DID listing and call routing while keeping the number saved. | - - If you select **Phone Number (DID)**, complete the next step. If you selected **Voice Provider: Bring Your Own SIP** instead, skip to Configure SIP Settings. + +### Configure the Realtime LLM Voice channel + +Once the channel is created, open it from the **Realtime LLM Voice** connections list. The connection has three tabs: **Settings**, **Speech**, and **Testing**. The **Settings** tab holds the voice provider and call routing. The **Speech** tab holds realtime orchestration, the S2S provider, and advanced voice behavior. The **Testing** tab holds the shareable softphone link. + + + + On the **Settings** tab, under **Realtime LLM Voice Settings**, set **Voice Provider** to **Kore.ai Voice Gateway** or **Bring Your Own SIP**. If you choose **Kore.ai Voice Gateway**, set the following under **Call routing**. Choose how calls reach this agent. Enable **Soft Phone** for browser testing, and add a phone number (DID) when the channel needs a real phone number. + | Route | Description | + | --- | --- | + | **Soft Phone** (FREE) | Dial the agent from your browser with no DID purchase or telephony charges. Use it for evals, QA, and demos. **Launch dialer** opens the browser dialer. | + | **Phone Number (DID)** | Purchase a real phone number through Twilio. Disable this route to stop DID listing and call routing while keeping the number saved. | + + Keep KoreVG as the managed telephony gateway unless your platform owner has approved another provider. Confirm that the realtime provider you plan to use is available for your tenant and environment. + + If you select **Phone Number (DID)**, complete the next step. If you selected **Voice Provider: Bring Your Own SIP** instead, skip to step 3. - - - Set the **Provider** to **Twilio**, toggle **Inbound calls** (route calls from this number into the voice agent) and **Outbound calls** (allow this number to be used for campaign dialout), and select a **Country**, **Number Type**, and optional **Area Code**. Select **Search Available Numbers** to list numbers that match your filters. + + - Set **Provider** to **Twilio**. + - Toggle **Inbound calls** (routes calls from this number into the voice agent). + - Toggle **Outbound calls** (allows this number for campaign dial‑out). + - Select a **Country**, **Number Type**, and optional **Area Code**. + - Choose **Search Available Numbers** to list matching numbers. + + Buy or assign a Twilio‑backed number from the saved connection’s settings. + - Confirm the number is bound to this connection before activation. + - After assignment, the number appears in the **Phone Number** field. + - Select **Remove** to unbind the number from the connection. - - - Once the channel is created, select it, then go to the **Configuration** tab. If you chose **Voice Provider: Bring Your Own SIP**, set the following fields under **SIP Configuration**. - - | Field | Description | - | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | **Our SIP Server Address** | Configure your SIP provider to send `INVITE` to this address, for example `korevg-np.kore.ai:5060`. Select **Copy** to copy the address. | - | **SIP Gateway IPs / CIDRs** | Provider SIP source addresses. Separate multiple IPv4 addresses or CIDR ranges with commas, for example `203.0.113.50:5080, 3.80.16.0/23`. | - | **SIP Termination URI** | Choose whether your SIP provider identifies by **IP Address** or **Domain Name**, then enter the SIP termination URI. | - | **DID / Phone Number** | The phone number (DID) your SIP provider routes to this SIP gateway. | - | **Enable E.164 (leading +)** | Prepend a leading `+` to outbound numbers sent to the carrier. On by default, which international (full-E.164) numbers require. Turn off only for local/national-format numbers — otherwise the leading `+` misroutes them. | + + If you chose **Bring Your Own SIP**, the **Call routing** options are replaced by a **SIP Configuration** section on the **Settings** tab. Set the following fields. + | Field | Description | + | --- | --- | + | **Our SIP Server Address** | A read-only address. Configure your SIP provider to send `INVITE` to this address, for example `korevg-np.kore.ai:5060`. Select **Copy** to copy the address. | + | **SIP Gateway IPs / CIDRs** | Provider SIP source addresses. Separate multiple IPv4 addresses or CIDR ranges with commas, for example `203.0.113.50:5080, 3.80.16.0/23`. | + | **SIP Termination URI** | The termination address your SIP provider expects outbound calls to reach, as either an **IP Address** or **Domain Name**. Select the type, then type the SIP termination IP address or domain name in the **SIP termination URI** field below it. | + | **DID / Phone Number** | The phone number (DID) your SIP provider routes to this SIP gateway. | + | **Enable E.164 (leading +)** | Prepend a leading `+` to outbound numbers sent to the carrier. On by default, which international (full-E.164) numbers require. Turn off only for local or national-format numbers, otherwise the leading `+` misroutes them. | - - - Under **Realtime LLM Voice settings**, set the following fields. - + + At the bottom of the **Settings** tab, for either voice provider, set the following. + | Field | Description | + | --- | --- | + | **Trust inbound SIP headers** | Off by default. Turn it on only if your SBC sets or overwrites these headers. If the headers can arrive from the caller, the value isn't trustworthy. When on, transfer headers configured to pass through from the inbound call (for example, `User-to-User`) are sent on the transfer. When off, they are dropped. | + | **Connection Name** | The system name of the connection. Select the copy icon to copy it. | + + Click **Save Changes** to apply the settings. + + + On the **Speech** tab, set the following fields. * **Realtime orchestration**: Select how runtime coordinates the conversation flow and business tool execution for realtime voice interactions. Realtime orchestration determines whether the realtime model or runtime controls conversation progression and business actions, such as bookings, orders, and payments. - + | Mode | Description | Recommended for | - | - | - | - | + | --- | --- | --- | | **Legacy - model-selected tools** | Preserves the existing behavior where the realtime model manages both the conversation and business tool selection. | Existing agents and backward compatibility. | | **Runtime Guarded - hybrid freeform (recommended)** | Allows the realtime model to conduct the conversation naturally while runtime validates tool execution and context updates against the current FLOW step. Business tools execute only when they belong to the active FLOW step, preventing out-of-order actions while maintaining the authored FLOW. | New realtime voice agents that require natural conversations while maintaining FLOW integrity. | | **Runtime Owned - canonical turn** | Runtime controls every conversation turn and executes the FLOW exactly as authored. The realtime model handles conversational responses but cannot invoke business tools directly. | Workflows involving payments, bookings, orders, or other irreversible business actions and highly deterministic flows. | - + - - Changes to the orchestration mode apply only to new realtime sessions. Calls already in progress continue using the mode that was active when the session started. - - Existing channel configurations without a configured orchestration mode continue to use Legacy behavior. + * Changes to the orchestration mode apply only to new realtime sessions. Calls already in progress continue using the mode that was active when the session started. + * Existing channel configurations without a configured orchestration mode continue to use Legacy behavior. - + * **Response wording owner**: Select who generates the wording of responses for realtime voice conversations. This setting is available only when the Realtime orchestration mode is set to **Runtime Owned — canonical turn**. * **Runtime text (recommended)**: Runtime generates the response text. This option provides consistent response generation. * **Provider-grounded voice**: Uses the realtime voice provider to generate spoken responses while runtime continues to control conversation flow and business actions. This option is available only for Gemini Live. For unsupported or unsafe conversation turns, it automatically falls back to runtime-generated text responses. - - * **Semantic convergence**: Semantic Convergence determines how the platform coordinates with the realtime voice provider during a voice interaction. Controls whether realtime voice turns use the coordinated utterance runtime. This setting is available only when the realtime orchestration config is set to **Legacy mode**. - + + * **Semantic convergence**: Semantic Convergence determines how the platform coordinates with the realtime voice provider during a voice interaction. Controls whether realtime voice turns use the coordinated utterance runtime. This setting is available only when the realtime orchestration config is set to **Legacy mode**. The **Effective at runtime** line below the setting shows the mode currently in effect. + | Mode | Description | Recommended use | - | - | - | - | + | --- | --- | --- | | **Off** | Uses the legacy realtime voice execution model. The realtime provider executes tool calls directly without semantic coordination. | Use for backward compatibility with existing voice applications. | | **Shadow** | Uses the legacy execution model while collecting diagnostics to compare legacy behavior with semantic convergence. Doesn't affect customer interactions. | Use for validation, testing, and migration before enabling **Enforce**. | | **Enforce** | Uses semantic convergence to route voice turns through the platform's coordinator, ensuring tool execution and business logic are processed consistently with the agent runtime. | Recommended for new realtime voice deployments and production environments requiring consistent behavior across voice and text. | - - * **S2S Provider**: The realtime speech-to-speech model the channel uses. Select one of the following: **Amazon Nova Sonic (S2S)**, **Azure OpenAI Realtime**, **Grok Realtime (S2S)**, **Google Gemini Live**, or **OpenAI Realtime**. Each option shows which credentials it uses: - + + * **S2S Provider**: The realtime speech-to-speech model the channel uses. Select an approved realtime provider and model, and match its audio format, locale, voice, and tool-calling capabilities to the agent. Select one of the following: **Amazon Nova Sonic (S2S)**, **Azure OpenAI Realtime**, **Grok Realtime (S2S)**, **Google Gemini Live**, or **OpenAI Realtime**. Each option shows which credentials it uses: + | Provider | Credentials used | - | - | - | + | --- | --- | | **Amazon Nova Sonic (S2S)** | Voice Service credentials (Amazon Nova Sonic (S2S) Credentials). | | **Azure OpenAI Realtime**, **Grok Realtime (S2S)**, **Google Gemini Live**, **OpenAI Realtime** | The project-selected model connection. See **Realtime model connection** below. | - - * **Realtime model connection**: Shown for every S2S provider except Amazon Nova Sonic, which authenticates via Voice Service credentials instead. Selects the project-pinned realtime model this provider uses - shows `Use project realtime model` until a workspace admin adds one: - + + * **Realtime model connection**: Shown for every S2S provider except Amazon Nova Sonic, which authenticates via Voice Service credentials instead. Selects the project-pinned realtime model this provider uses. It shows `Use project realtime model` until a workspace admin adds one. The **Source** line below the dropdown shows where the model comes from, and the deployment uses this exact model connection. To add one: + 1. Configure the model under [Voice Services](/agent-platform/administration/ai-configuration#voice-services), then add it to the [model catalog](/agent-platform/administration/ai-configuration#model-catalog) as an LLM provider. - 2. In the project, go to **Settings** -> **Model** and add the model you configured at the workspace level. - + 2. In the project, go to **Settings** > **Models** and add the model you configured at the workspace level. See [Models](/agent-platform/administration/general-settings#models). + * **Provider-specific settings**: After you select an S2S provider, a configuration section for that provider appears. Expand the provider below to see its settings. - + Under **Amazon Nova Sonic Configuration**, set the following fields. - + | Field | Description | - | - | - | + | --- | --- | | **Voice** | The voice Nova Sonic uses to speak to callers. Default: **Tiffany**. | | **Model** | The Amazon Bedrock model ARN, for example `arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-2-sonic-v1:0`. | | **Maximum tokens** | The maximum number of tokens in a model response. Default: `1024`. | | **Temperature** | Controls response randomness. Lower values give more predictable responses; higher values give more varied responses. Default: `0.70`. | | **Top P** | Limits the model to the smallest set of likely tokens whose combined probability reaches this value. Default: `0.90`. | | **Endpointing sensitivity** | How quickly Nova decides the caller has finished speaking. **Medium** (default) suits general conversation. **High** responds sooner but may interrupt callers. **Low** allows more pause before responding. | - + **Pending tool fillers** - + Turn on **Pending tool fillers** to let Nova speak a brief hold phrase when a project tool is still running. Fast tools finish without a filler. - + | Field | Description | - | - | - | + | --- | --- | | **Filler delay (milliseconds)** | Nova speaks only if the tool is still pending after this delay. Leave empty to use the default of `900` ms. | | **Tool filler instruction** | The instruction Nova follows to generate the hold phrase. Use `{{toolName}}` to insert the name of the running tool. Default: `The tool {{toolName}} is still in progress. Briefly tell the caller that you are working on it.` | - + **Coordinator turn filler** - + Turn on **Coordinator turn filler** to let Nova speak a short hold phrase during convergence-enabled coordinator turns while Runtime decides and executes the turn. - + | Field | Description | - | - | - | + | --- | --- | | **Coordinator filler instruction** | The instruction Nova follows to generate the hold phrase. Default: `Briefly tell the caller that you are still working on their request.` Runtime sends this as native cross-modal input and keeps its transcript out of the canonical conversation history. | - + **Advanced voice behaviour (Nova-specific)** - + | Field | Description | - | - | - | + | --- | --- | | **Failed tool call fallback** > **Tell the caller and end the call** | When a Nova tool call fails, Nova says a short apology and ends the call. Off by default. | - + Also configure the **Advanced voice behaviour** settings that apply to all providers, described after the provider list. - + Under **Azure OpenAI Realtime Configuration**, set the following fields. - + | Field | Description | - | - | - | + | --- | --- | | **Voice** | The voice used to speak to callers. Default: **Marin (recommended)**. | | **Temperature** | Controls response randomness. Range: **Focused** (`0.6`) to **Creative** (`1.2`). Default: `0.8`. | - + **Turn detection** - + | Field | Description | - | - | - | + | --- | --- | | **Speech detection sensitivity** | Adjusts how readily the model detects speech. Default: `0.5`. | | **Silence Duration (ms)** | How long the caller must be silent before the turn is treated as complete. Default: `700`. | | **Prefix Padding (ms)** | Audio kept before detected speech so the start of the caller's utterance is preserved. Default: `300`. | - + Also configure the **Advanced voice behaviour** settings that apply to all providers, described after the provider list. - + Under **Grok Realtime Configuration**, set the following fields. - + | Field | Description | - | - | - | + | --- | --- | | **Voice** | The voice used to speak to callers. Default: **Ara**. | | **Temperature** | Controls response randomness. Range: **Focused** (`0.0`) to **Creative** (`2.0`). Default: `0.8`. | | **Threshold** | Controls speech detection. Range: **Sensitive** (`0.0`) to **Conservative** (`1.0`). Default: `0.5`. | | **Silence Duration (ms)** | How long the caller must be silent before the turn is treated as complete. Default: `500`. | | **Prefix Padding (ms)** | Audio kept before detected speech so the start of the caller's utterance is preserved. Default: `300`. | - + Also configure the **Advanced voice behaviour** settings that apply to all providers, described after the provider list. - + Under **Gemini Live Configuration**, set the following fields. - + | Field | Description | - | - | - | + | --- | --- | | **Voice** | The voice used to speak to callers, for example **Puck — Upbeat**. | | **Enable context window compression** | Lets Gemini compress older session context so long-running Live conversations can continue beyond the model's context window. Off by default. | | **Temperature** | Controls response randomness. Range: **Deterministic** (`0.0`) to **Creative** (`2.0`). Default: `0.8`. | - + **Tool response scheduling** - + | Field | Description | - | - | - | + | --- | --- | | **Tool response scheduling** | Controls how Gemini resumes after a final tool result. **Interrupt** responds immediately to the final result. **When idle — finish the current response first** (default) waits for the current response to finish. **Silent** retains the final result without speaking right away. Progress and filler updates always wait until Gemini is idle. | | **Pending tool fillers** | Lets Gemini Live acknowledge long-running project tools while the original tool call remains pending. Off by default. | - + **Realtime turn filler** - + Separate from project Voice Fillers. Applies only to Google or Vertex realtime S2S calls while semantic convergence is set to **Enforce**. - + | Field | Description | - | - | - | + | --- | --- | | **Native turn filler** | Lets Gemini speak a short hold phrase while Runtime settles an enforced turn. It never applies to transfers, handoffs, or protected playback. | | **Generative native filler** | Lets Gemini choose a short, contextual hold phrase in the current language instead of using the deterministic phrase pool. | | **Generative filler prompt override** | Overrides the prompt Gemini uses to generate the hold phrase. Default: `Reply with a short, natural hold phrase in the current language.` | - + **Filler delivery safeguards** - + Shared by pending-tool and realtime turn fillers. - + | Field | Description | - | - | - | + | --- | --- | | **Settlement watchdog** | Time allowed for filler generation or a held final response to settle before Runtime releases the safe fallback. Accepted range: `1000`–`60000` ms. Leave empty to use the platform default of `10000` ms. | - + **Voice activity detection** - + Controls when Gemini starts listening to a caller turn and how long it waits before closing that turn. - + | Field | Description | - | - | - | + | --- | --- | | **Start Sensitivity** | Higher detects speech sooner but may trigger on noise. Lower waits for a stronger speech signal. Default: **Default**. | | **End Sensitivity** | Higher ends turns sooner for lower latency. Lower allows longer pauses before Gemini responds. Default: **Default**. | | **Silence Duration (ms)** | Milliseconds of non-speech before Gemini closes the caller turn. Increase to allow pauses; decrease for faster responses. Default: `100`. | | **Prefix Padding (ms)** | Milliseconds of detected speech required before Gemini commits a speech start. Lower values catch shorter utterances but can increase false starts. Default: `20`. | - + **Caller transcription** - + | Field | Description | - | - | - | + | --- | --- | | **Caller language** (Optional) | The language callers speak, such as `en-US`. If left empty, Gemini guesses the language on every turn, which can turn English into another script. The call's language setting, when there is one, takes precedence. | - + **Silent-turn recovery** - + | Field | Description | - | - | - | + | --- | --- | | **Recover silent turns** | Re-prompts, then restarts, a Gemini session that stays silent when it owes the caller an answer. | | **Recover unanswered caller turns only** | Limits recovery to caller turns that received no answer. Included automatically when **Recover silent turns** is on. If Gemini hears the caller but does not respond within 8 seconds, the Gemini session restarts with the caller's words, without re-prompting tool results. | - + **Advanced voice behaviour (Gemini-specific)** - + | Field | Description | - | - | - | + | --- | --- | | **Silent resume recovery** > **Recover a silent resumed session** | Starts a fresh Gemini session when a resumed one connects but never speaks. Off by default. | - + Also configure the **Advanced voice behaviour** settings that apply to all providers, described after the provider list. - + Under **OpenAI Realtime Configuration**, set the following fields. - + | Field | Description | - | - | - | + | --- | --- | | **Voice** | The voice used to speak to callers. Default: **Marin (recommended)**. | - + **Turn detection** - + Tune how OpenAI detects when speech starts and when the caller has finished speaking. - + | Field | Description | - | - | - | + | --- | --- | | **Turn detection mode** | How OpenAI detects turns, for example **Server VAD — audio activity**. | | **Speech detection sensitivity** | Range: **More sensitive** (`0.0`) to **More conservative** (`1.0`). Lower values pick up quieter speech; higher values reduce background-noise triggers. Default: `0.5`. | | **Silence Duration (ms)** | Quiet time before OpenAI treats the caller turn as complete. Default: `700`. | | **Prefix Padding (ms)** | Audio kept before detected speech so the beginning of the caller's utterance is preserved. Default: `300`. | - + **Caller transcription** - + How the caller's speech is written down. This text is stored as the caller's turn and is what the agent checks answers against. - + | Field | Description | - | - | - | + | --- | --- | | **Caller transcriber** | The transcription model, for example **Whisper (default)**. | | **Caller language** (Optional) | The language callers speak, such as `en-US`. If left empty, the transcriber guesses the language on every turn, which can turn English into another script. | | **Words to expect** | Brand names and terms callers use, for example `Acme, Rewards, email addresses spelled out letter by letter`. Used by Whisper and GPT-4o Transcribe. | - + Never put a caller's own details in **Words to expect**. The transcriber would then hear them from anyone. - + **Realtime turn filler** - - Configure turn fillers to play short hold phrases while the agent processes a caller's request. - + + Applies only to OpenAI Realtime calls while semantic convergence is set to **Enforce**. Off by default. + | Field | Description | | --- | --- | - | **Native turn filler** | Enables the model to generate short hold phrases in the caller's language while Runtime processes the caller's turn. Hold phrases stop when the answer is ready, do not play during a transfer or handoff, and are not added to the conversation. | - | **Filler prompt override** (Optional) | Replaces the default instruction used to generate hold phrases. Runtime appends fixed safety rules to prevent the model from making claims about results, actions, promises, questions, or tool calls. | - - The model generates fillers based on the caller's language and context. The agent's final answer is spoken after the filler finishes, preventing the filler and answer from overlapping. + | **Native turn filler** | While Runtime works on a caller turn, OpenAI says a short hold phrase in the caller's language. Hold phrases stop when the answer is ready, never play during a transfer or handoff, and aren't added to the conversation. | + | **Filler prompt override** (Optional) | Replaces the default instruction OpenAI words each hold phrase from. Default: `Reply with a short, natural hold phrase in the current language.` Runtime appends fixed safety rules that prevent claims about results, actions, promises, questions, or tool calls. | + + **Advanced voice behaviour (OpenAI-specific)** + + | Field | Description | + | --- | --- | + | **Caller interruption** > **Let callers interrupt the agent** | When off, the caller speaking doesn't cut off what the agent is saying. | + | **Caller interruption** > **Protect non-interruptible outputs** | Uses model playback for protected outputs and protects the welcome unless interruption is allowed. Off by default. With server VAD, turning this on lets the model play protected outputs and protects the welcome unless `ON_START` allows interruption. An `ON_START` greeting authored with barge-in disallowed is protected automatically with server or semantic VAD, regardless of this switch. Input that repeats a protected output word for word is treated as echo. Menu answers, numbers, spelled names, and other caller input still run. | + | **Silent caller reprompt** > **Reprompt a silent caller** | Uses the project's voice no-input settings (timeout, reprompt messages, retries, and final action) on this realtime channel. Turn it off to keep the channel silent. | + | **Caller transcript cross-check** > **Check the model's wording against the transcript** | Waits briefly for the caller's transcript and gives it to the agent beside what the model reported. | + | **Longest wait for the transcript (ms)** (Optional) | Sets how long the turn waits for the caller's transcript, up to 5000 ms. Leave empty to size the wait to the caller transcription model of the selected realtime model: 1500 ms for `whisper-1` and 400 ms for `gpt-4o` transcription. The turn runs without the transcript once the wait ends. | + + Also configure the **Advanced voice behaviour** settings that apply to all providers, described after the provider list. - + * **Advanced voice behaviour (all providers)**: Optional behaviours for this channel. Each one is off, empty, or set to the earlier platform behaviour until you change it. - + | Field | Description | - | - | - | + | --- | --- | | **Caller wording** > **Wording a caller turn runs on** | Select the wording the agent runs a caller turn on: **Model's wording** (default), **Auto: prefer the caller's transcript**, or **Caller transcript**. | | **Default transfer announcement** > **Line spoken before a transfer** (Optional) | The line the agent speaks before a transfer, for example `One moment while I connect you.` | - - * **Noise isolation**: Applies server-side noise reduction to inbound call audio to filter out background voices and ambient noise. - - * **Voice transfer and survey capabilities**: A read-only panel that shows which transfer and survey capabilities Runtime supports for the selected provider. + | **Runtime-owned speech** > **Speak Runtime answers exactly** | Runtime makes the voice model say its answers word for word, once per caller turn, and records what was said. | + | **Noise isolation** | Applies server-side noise reduction to inbound call audio to filter out background voices and ambient noise. | + | **Trust inbound SIP headers** | The same setting as on the **Settings** tab. Off by default. Turn it on only if your SBC sets or overwrites these headers. | + + * **Voice transfer and survey capabilities**: A read-only panel that shows how many of the transfer and survey capabilities Runtime evaluates as available for the concrete voice execution boundary (the execution surface is **KoreVG realtime S2S**), for example **11 of 11 capabilities available**. It lists the following capabilities, each marked **Available** or not. + + | Capability | Description | + | --- | --- | + | **Human transfer** | Transfer the caller to a human agent. | + | **Pre-transfer announcement** | Speak an announcement before a transfer. | + | **Transfer outcome recovery** | Recover when a transfer doesn't complete. | + | **SIP transfer** | Transfer the call over SIP. | + | **PSTN transfer** | Transfer the call to a phone number on the public telephone network. | + | **Bridged agent transcript** | Carry the transcript to the agent the call is bridged to. | + | **Transfer CSAT** | Collect a satisfaction rating after a transfer (`csat`, `nps`, `likeDislike`). | + | **Template survey** | Run a template survey with a rating type of `star`, `thumbs`, or `scale`. | + | **Survey comments** | Collect free-text comments in a survey. | + | **Survey follow-ups** | Ask follow-up questions in a survey. | + | **Return-leg survey** | Run a survey on the return leg of a transferred call. | + + Click **Save Changes** on the **Speech** tab to apply the settings. + + + Resolve any missing provider credentials and model configuration before you test. After you save, confirm that Studio shows the phone number on the saved connection. Each tab has its own **Save Changes** button, so save on each tab you edit. + Don't repoint shared KoreVG or softphone hosts. Phone registration, device call, Jambonz API, and SBC hosts are shared environment settings. Only a connection-specific callback may target a local tunnel during isolated testing. -### Manage an existing realtime LLM voice channel +### Test the Realtime LLM Voice Channel -Open a channel from **Deployments** > **Channels** > **Voice** > **Realtime LLM Voice**. It contains three tabs: **Overview**, **Configuration**, and **Deployment**. +Open the **Testing** tab to verify the channel before going live. - - - **Connection Summary** displays the following fields. - - | Field | Description | - | ----------------- | -------------------------------------- | - | **Status** | For example: `Active` | - | **Created** | Timestamp the channel was created | - | **Updated** | Timestamp of the last change | - | **Environment** | For example: `dev` | - | **Source Type** | Realtime LLM Voice Channel | - | **Source ID** | Unique identifier (UUID) of channel | - - - - The channel includes the same **General** (Display Name), **Provider Verification Strength**, call routing, **Realtime LLM Voice Settings**, and provider-specific settings (which vary by the selected S2S provider) described in [Set up Realtime LLM Voice](#set-up-realtime-llm-voice-channel). You can edit these settings any time and with immediate effect. - +- **Shareable softphone link:** Generate a time‑limited link that lets anyone call the channel from a phone browser through the real gateway and view a read‑only transcript. + - Links expire after 7 days and can be revoked at any time. + - **Active links** shows links currently in use, or **No active links for this channel**. + - Viewing active links requires read access; generating or revoking links requires edit permission. - - The **Deployment** tab displays these fields. +- **Soft Phone dialer:** From the **Settings** tab, select **Soft Phone > Launch dialer** to call the agent directly from your browser. + - No DID purchase or telephony charges are required. - | Field | Description | - | ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | - | **Agent Version** | An **Environment** dropdown (for example: `Development`) that selects which deployed version handles incoming messages. | - | **Active Deployment** | Displays the bound deployment version and when it was deployed. | +### Verify and secure the Realtime LLM Voice channel + +Before you go live, validate the quality of realtime calls. Realtime quality depends on the slowest leg of the call, so test each of the following. + + + + Generate a time‑limited preview, allow microphone access, start and stop a call, mute/unmute, and confirm chat remains usable if microphone or provider setup fails. + + + Dial the provisioned number and validate greeting, bidirectional audio, tool execution, transfer/termination, caller hang‑up, and one stable Runtime session. + + + Record gateway connect time, provider session setup, input audio commit, first model audio, end‑to‑end turn p50/p95, jitter, and packet loss. + + + Interrupt a long agent response, speak immediately, and verify stale audio is cancelled, tool calls aren’t duplicated, and the next user turn is preserved. + + + Deny microphone access, force provider disconnect, gateway reconnect, model timeout, tool failure, phone hang‑up, and capacity rejection. Confirm caller hears or receives the designed fallback. + + - Click **Save Changes** after switching the environment/version. - - +### Security, Latency, and Reliability Practices + +- **Protect credentials:** Treat realtime provider and carrier credentials as administrator‑managed secrets. Do not copy API keys into connection identifiers, browsers, screenshots, or agent prompts. +- **Minimize overhead:** Avoid unnecessary transcoding, buffering, proxy hops, and oversized tool responses. Set explicit connection and turn timeouts, and verify heartbeat behavior through every proxy. +- **Validate capacity:** Check provider concurrency, KoreVG session limits, phone capacity, and backpressure before load tests. Capacity rejection must fail predictably, not degrade active calls. +- **Define fallback behavior:** Specify caller‑visible handling for provider unavailability, timeout, safety rejection, tool failure, and transfer failure. Include rules for retry, reprompt, mode switch, or call termination. +- **Trace sessions:** Capture call/session IDs, provider events, tool calls, turn latency, interruptions, errors, and termination reasons. Scrub audio, transcripts, and credential data from logs. + +### Manage an existing Realtime LLM Voice channel + +Open a channel from **Deployments** > **Channels** > **Voice** > **Realtime LLM Voice** and select a connection. The connection header shows the display name, its status (for example, *Active*), and when it was last updated. The connection has three tabs. + +| Tab | Description | +| --- | --- | +| **Settings** | The **Display Name**, **Realtime LLM Voice Settings** (**Provider Verification Strength**, **Voice Provider**, and **Call routing** or **SIP Configuration**), **Trust inbound SIP headers**, and **Connection Name**. Described in [Configure the Realtime LLM Voice channel](#configure-the-realtime-llm-voice-channel). | +| **Speech** | **Realtime orchestration**, **Semantic convergence**, the **S2S provider** and its settings, and **Advanced voice behaviour**. Described in step 5 of [Configure the Realtime LLM Voice channel](#configure-the-realtime-llm-voice-channel). | +| **Testing** | The shareable softphone link and active links. Described in [Test the Realtime LLM Voice channel](#test-the-realtime-llm-voice-channel). | + +Changing settings on the **Settings** or **Speech** tab updates the live channel after you click **Save Changes**. + +### Troubleshoot Realtime LLM Voice + +* **Calls to the number fail:** an **Active** phone-routed connection without a provisioned number can't receive production PSTN calls. Assign or buy a number, and confirm it's bound to this connection. +* **The channel can't start a session:** resolve missing provider credentials and model configuration, then save the connection and test again. +* **Duplicate tool calls or stale audio after an interruption:** repeat the barge-in test from [Verify and secure the Realtime LLM Voice channel](#verify-and-secure-the-realtime-llm-voice-channel) and check the traces for the affected call and session IDs. + For the full validation checklist, click **Setup instructions** on the Realtime LLM Voice channel page. ## Set up Pipeline Voice channel diff --git a/agent-platform/channels/whatsapp.mdx b/agent-platform/channels/whatsapp.mdx index 595689bc4..8c96bf4e1 100644 --- a/agent-platform/channels/whatsapp.mdx +++ b/agent-platform/channels/whatsapp.mdx @@ -5,51 +5,109 @@ sidebarTitle: WhatsApp [Back to messaging or digital channels](/agent-platform/channels#messaging-or-digital-channels) -Connect your agent to a WhatsApp Business sender so customers reach it from WhatsApp. Artemis reaches WhatsApp through a Business Solution Provider, and the provider you choose decides which credentials you collect, which webhook route you register, and where the sender lives. +Connect your agent to a WhatsApp Business sender so customers reach it from WhatsApp. Artemis reaches WhatsApp through a Business Solution Provider (BSP): Meta Cloud API, Infobip, or Gupshup. The provider you choose decides which credentials you collect, which webhook route you register, how Artemis verifies inbound traffic, and who owns the sender. The setup requires: -1. [Choose a provider](#choose-a-provider-first), then complete either [Meta setup](#meta-setup) or [Infobip setup](#infobip-setup) to collect the routing identifier and credentials. -2. [Artemis channel configuration](#artemis-channel-configuration) using those values, then copy the generated webhook URL. -3. [Webhook configuration with your provider](#webhook-configuration-with-your-provider): register the callback URL so inbound messages reach Artemis. +1. [Choose a provider](#choose-a-provider) before you collect any value. +2. Complete the provider setup for your choice: [Meta setup](#meta-setup), [Infobip setup](#infobip-setup), or [Gupshup setup](#gupshup-setup). +3. [Artemis channel configuration](#artemis-channel-configuration): create the connection with the provider's values, then copy the generated webhook URL. +4. [Webhook configuration with your provider](#webhook-configuration-with-your-provider): register the callback URL so inbound messages reach Artemis. +5. [Verify the connection](#verify-the-connection) with a real two-way WhatsApp conversation. -After you complete the configuration, your provider posts inbound WhatsApp messages to Artemis, which matches the sender identifier to this connection and hands the message to the deployed agent. +After you complete the configuration, your provider posts inbound WhatsApp messages to Artemis. The runtime matches the business sender in each callback to a saved connection, verifies the callback, and hands the message to the agent deployed in the bound environment. The agent's reply goes back out through the same provider. **Important considerations** -- **The provider selector changes the whole setup**: It decides which credential fields the dialog shows and which webhook route you register. Credentials from one provider never work with another's route, so pick the provider before you collect anything. -- **Who owns the WhatsApp Business account differs by provider**: On Meta Cloud API, you hold it directly and Meta issues a test sender in minutes. That's why most projects start there. On Infobip, Infobip holds it and onboards the sender for you, which removes the Meta paperwork at the cost of a provisioning wait. -- **The Meta test token expires within 24 hours**: To test and not to run. See [Create a permanent access token](#create-a-permanent-access-token). -- **Verification proves less than it appears to**: A webhook that returns 2xx proves only that your provider reached the runtime. It says nothing about whether your outbound credentials work. +- **The provider selector changes the whole setup**: It decides which fields the dialog shows, which webhook route the connection generates, and which in-product setup guide appears. Values from one provider never work on another provider's route, so pick the provider first and keep every value on that single path. +- **Who owns the WhatsApp Business account differs by provider**: On Meta Cloud API, you hold the account directly and Meta issues a test sender in minutes. On Infobip and Gupshup, the provider holds the account and onboards the sender for you, which removes the Meta paperwork at the cost of a provisioning wait. +- **Inbound verification strength differs by provider**: Meta signs every callback with your App Secret. Gupshup can send a signed bearer token if you set a JWT secret. Infobip sends no signature at all, so you protect its route with network controls instead. +- **The Meta test token expires within 24 hours**: It's enough to test and not enough to run. See [Create a permanent access token](#create-a-permanent-access-token). +- **A verified webhook proves less than it appears to**: A 2xx response proves only that your provider reached the runtime. It says nothing about whether your outbound credentials work, so always finish with a real two-way conversation. ## Prerequisites -- An account with your chosen Business Solution Provider: A Meta developer account, or an Infobip account. -- For production on either path, the business details Meta requires for verification. Both routes wait on Meta review, so start early. -- An HTTPS-reachable Artemis runtime, since Meta calls the callback URL during verification. +Collect these before you open the connection dialog, because Meta and the BSPs both gate production on review time you can't shorten. + +- An account with your chosen provider: a Meta developer account, an Infobip account, or a Gupshup Enterprise WhatsApp account. +- For production on any path, the business details Meta requires for verification. Every route waits on Meta review, so start early. +- An HTTPS-reachable Artemis runtime, since providers call the callback URL from the public internet. - Artemis project access with permission to open **Deployments** -> **Channels**, and a deployed agent in the environment you intend to bind. --- -## Choose a provider first +## Choose a provider + +Each card jumps to that provider's setup. Read the comparison below the cards first if you haven't picked one yet. + + + + You own the account. Fastest test sender, strongest inbound verification. + + + Infobip owns the sender. Inbound traffic relies on network allowlisting. + + + Gupshup owns the sender. Optional JWT verification on inbound traffic. + + -Pick the provider before you collect anything, and keep the identifier, credentials, webhook route, and provider-side sender on that single path. +### What each provider needs + +The routing identifier tells the runtime which connection an inbound callback belongs to. The credentials authenticate outbound messages and, where the provider supports it, inbound callbacks. | Provider | Routing identifier | Credentials | |---|---|---| -| **Meta Cloud API** | Phone Number ID | Access Token and Phone Number ID for outbound, App Secret and Verify Token for inbound verification | -| **Infobip** | WhatsApp phone number, digits only | API Base URL with an API key or basic auth, plus a network allowlist for inbound verification | -| **Gupshup** | Business number the provider sends in the callback body | API username and password, plus an optional bearer token secret for inbound verification | +| **Meta Cloud API** | Phone Number ID | Access Token and Phone Number ID for outbound. App Secret and Verify Token for inbound verification. | +| **Infobip** | WhatsApp phone number, digits only | API Base URL plus an API key or a username and password for outbound. Inbound verification relies on a network allowlist. | +| **Gupshup** | WhatsApp business number, digits only | API username and password for outbound. An optional Webhook JWT Secret for inbound verification. | + +### Webhook route and inbound verification -Each provider also has its own webhook route. Meta uses the generic WhatsApp route, while Infobip and Gupshup each add their provider slug to the URL. Copy the route that matches the provider you selected in Artemis rather than assuming one URL serves all three. +Each provider gets its own route on the runtime, and the connection generates the right one for you. The route decides which payload format and which verification model the runtime applies. -Work through the provider section that matches your choice, then rejoin the shared path at [Artemis channel configuration](#artemis-channel-configuration). +| Provider | Webhook route | How the runtime verifies inbound callbacks | +|---|---|---| +| **Meta Cloud API** | `/whatsapp/webhook` | Checks the `X-Hub-Signature-256` HMAC-SHA256 signature over the raw request body, using your App Secret. A GET challenge using your Verify Token verifies the URL itself. | +| **Infobip** | `/whatsapp/infobip/webhook` | No request signature. You restrict ingress with provider IP allowlists, a trusted gateway, or other network controls. | +| **Gupshup** | `/whatsapp/gupshup/webhook` | Validates an `Authorization: Bearer` JWT, HS256 by default, when you set a Webhook JWT Secret. With the field blank, it skips cryptographic verification. | + +Never append a phone number, connection ID, or provider slug to these routes yourself. The runtime reads the sender from the callback body. + +--- + +## 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. + +| Provider | Inbound field the runtime reads | Common mix-up | +|---|---|---| +| **Meta Cloud API** | `metadata.phone_number_id` | The display phone number or the WhatsApp Business Account ID | +| **Infobip** | `results[0].to` | A formatted number with spaces or punctuation | +| **Gupshup** | `body.waNumber` | The customer's number, which Gupshup sends as `body.mobile` | + +The path also splits troubleshooting in two. A session in **Sessions** means the inbound half worked and the outbound half failed. No session means nothing passed routing and verification. --- ## Meta setup -Complete this section only if you selected Meta Cloud API. Everything here happens in Meta, before you open Artemis, and each screen depends on the one before it. Meta covers the same ground in its own words in the [Cloud API get started guide](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started). +Complete this section only if you selected Meta Cloud API. Everything here happens in Meta before you open Artemis, and each screen depends on the one before it. Meta covers the same ground in its [Cloud API get started guide](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started). @@ -64,13 +122,13 @@ Complete this section only if you selected Meta Cloud API. Everything here happe 2. 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. 3. Enter an app name and a contact email, attach a Meta Business portfolio if you have one, and create the app. - The app type matters, because only a business app exposes the WhatsApp product. Meta opens the App Dashboard once the app exists. + Only a business app exposes the WhatsApp product. Keep development and production on separate apps or separate phone numbers, so test traffic never reaches customer conversations. - 1. On the App Dashboard, scroll the **Add products to your app** list to **WhatsApp** and select **Set up**. If you've navigated away from that screen, the left menu carries an **Add product** entry that returns you to the same list. + 1. On the App Dashboard, scroll the **Add products to your app** list to **WhatsApp** and select **Set up**. If you've navigated away, the **Add product** entry in the left menu returns you to the same list. - Meta provisions several things at once: a test WhatsApp Business Account, a test business phone number, and a set of pre-approved message templates. The test number reaches up to five verified recipients at no cost. The left menu now shows a **WhatsApp** section containing **API Setup** and **Configuration**, which are the two screens you'll use. + Meta provisions a test WhatsApp Business Account, a test business phone number, and a set of pre-approved message templates. The test number reaches up to five verified recipients at no cost. The left menu now shows a **WhatsApp** section containing **API Setup** and **Configuration**, the two screens you'll use. All of this is test infrastructure. It works for development and none of it works for production. @@ -81,7 +139,7 @@ Complete this section only if you selected Meta Cloud API. Everything here happe 1. Select **Generate access token** and complete the prompt, then copy the token. Meta issues a fresh one each time you open this panel, and it expires within 24 hours. 2. Below the **From** field, Meta shows the test business phone number, and directly beneath that, a numeric **Phone Number ID**. Copy the ID. - The Phone Number ID isn't the phone number. It's Meta's internal identifier for the sender, and entering the displayed number instead is the most common reason a connection never receives traffic. The two values sit next to each other on this screen, which is exactly why they get swapped. + The Phone Number ID isn't the phone number, and it isn't the WhatsApp Business Account ID either. It's Meta's numeric resource ID for the sender. Entering either of the other two values is the most common reason a connection never receives traffic, and all three sit close together in Meta's screens. See [Create a permanent access token](#create-a-permanent-access-token) before you move past testing. @@ -93,13 +151,13 @@ Complete this section only if you selected Meta Cloud API. Everything here happe 2. Select **Show** beside **App secret**. 3. Re-enter your Facebook password when Meta asks, then copy the value. - Meta signs every inbound callback with this secret, and Artemis checks that signature. A wrong value here means every inbound message fails verification even though the webhook itself verified successfully, which makes it a confusing failure to diagnose later. + Meta signs every inbound callback with this secret, and Artemis checks that signature. A wrong value fails every inbound message even though the webhook itself verified successfully, which makes it a confusing failure to diagnose later. - Choose any secret string. Meta doesn't issue this one, so you invent it and use the same value in two places: the Artemis connection, and the webhook configuration in Meta. A mismatch fails webhook verification. + Meta doesn't issue this value. You invent a high-entropy secret string and use it in two places: the Artemis connection and the webhook configuration in Meta. - Treat it as a secret rather than a label, and store it where you can retrieve it, because Meta shows it back to you only while you edit the webhook. + The runtime finds the connection by its Verify Token during the handshake, so give each connection its own value. Store it where you can retrieve it, because Meta shows it back to you only while you edit the webhook. @@ -117,30 +175,74 @@ Complete this section only if you selected Meta Cloud API. Everything here happe ## Infobip setup -Complete this section only if you selected Infobip. Infobip owns the WhatsApp Business account and the sender. You collect three things from the Infobip web interface instead of from Meta: the sender number, your account's API base URL, and an API key. +Complete this section only if you selected Infobip. Infobip owns the WhatsApp Business account and the sender. You collect the sender number, your account's API base URL, and one set of outbound credentials from the Infobip web interface. - - 1. Sign in to the [Infobip web interface](https://portal.infobip.com/login/). + + 1. Sign in to the [Infobip web interface](https://portal.infobip.com/login/) with the account and workspace that own the sender you intend to connect. 2. Go to **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders**. - 3. Note the sender number. Artemis wants it as digits only, with no plus sign, spaces, or punctuation. + 3. Complete sender onboarding if the sender isn't live yet, then note the sender number. - A trial account comes with a shared test sender that reaches numbers you verify, which is enough to prove the integration works. A production sender goes through Infobip onboarding, where Infobip registers the number with Meta and runs business verification on your behalf. Infobip's [WhatsApp over API guide](https://www.infobip.com/docs/whatsapp/whatsapp-over-api) covers what the channel supports once the sender is live. Start that process early, because it waits on Meta review rather than on Infobip. + A trial account comes with a shared test sender that reaches numbers you verify, which is enough to prove the integration works. A production sender goes through Infobip onboarding, where Infobip registers the number with Meta and runs business verification for you. Infobip's [WhatsApp over API guide](https://www.infobip.com/docs/whatsapp/whatsapp-over-api) covers what the channel supports once the sender is live. Start early, because onboarding waits on Meta review. - Infobip gives every account a personalized base URL in the form `xxxxx.api.infobip.com`, which you'll see on the homepage once you sign in. Infobip explains the scheme under [base URL](https://www.infobip.com/docs/developer-resources/about-infobip-apis/base-url). + Infobip gives every account a personalized base URL in the form `xxxxx.api.infobip.com`, shown on the homepage once you sign in. Infobip explains the scheme under [base URL](https://www.infobip.com/docs/developer-resources/about-infobip-apis/base-url). This URL isn't a credential. It routes your requests to the data center serving your account, so a wrong one degrades or fails the integration rather than exposing it. Enter it in Artemis with the `https://` scheme. - - 1. Go to **Developer Tools** -> **API Keys** and create a key for this integration. - 2. Copy the key when Infobip displays it and store it in your secret manager. + + Artemis authenticates outbound calls with either an API key or a username and password. Pick one and fill in only that method's fields. - Infobip also shows an existing key on the homepage, but a dedicated key per integration lets you revoke this one without disturbing anything else. + 1. To use an API key, go to **Developer Tools** -> **API Keys**, create a key for this integration, and copy it into your secret manager when Infobip displays it. + 2. To use basic authentication, note the username and password your account uses, and select basic authentication when you create the connection. - If your account authenticates with a username and password instead, note those rather than a key, and select basic authentication as the method when you create the connection. + Prefer a restricted API key where your account supports one. A dedicated key per integration lets you revoke this one without disturbing anything else. + + + + Infobip doesn't sign its callbacks, and the API key authenticates only your outbound calls. It never authenticates Infobip's calls to you. + + 1. Ask your Infobip contact which source addresses their platform sends webhooks from. + 2. Arrange an allowlist, a trusted gateway, or equivalent network controls in front of the Artemis route before you go live. + + + +--- + +## Gupshup setup + +Complete this section only if you selected Gupshup. Gupshup owns the WhatsApp Business account and the sender, and you collect the business number and the account's API credentials. The Artemis Gupshup fields take an Enterprise account's user ID and password and route on the `waNumber` field that Enterprise callbacks carry. + + + + 1. Sign in to the Gupshup account that owns the intended WhatsApp sender. + 2. Confirm with Gupshup that it's an Enterprise WhatsApp account that authenticates with a user ID and password. + + Gupshup's self-serve WhatsApp apps authenticate with an API key and post a different callback payload, so they don't fit these fields. Keep production credentials on a separate account from sandbox or development accounts. Some Enterprise setups split template messaging and two-way messaging across separate account IDs, so confirm which account carries two-way conversations. + + + + 1. Note the WhatsApp business number Gupshup provisioned for the account, as digits only with the country code. + + This is the number Gupshup sends as `body.waNumber` in every inbound callback, and it becomes the routing identifier in Artemis. Don't use the customer's number, which Gupshup sends as `body.mobile` in the same callback. + + + + 1. Note the user ID and password for the account. Gupshup issues them when it creates the account. + 2. Store both in your secret manager. + + These credentials authorize every outbound Gateway API call Artemis makes. Rotate them on your Gupshup account's policy. Gupshup's [API reference](https://docs.gupshup.io/docs/api-reference) shows how the Gateway API uses them. + + + + The Webhook JWT Secret is optional. Set it only when Gupshup or a trusted gateway in front of Artemis sends an `Authorization: Bearer` JWT signed with the same secret. + + 1. Agree on the shared secret with whoever signs the token. + 2. Store it in your secret manager for the Artemis connection. + + Leaving the field blank skips cryptographic verification, so protect the route with network controls instead. Setting it without a matching signer rejects every callback. @@ -148,113 +250,178 @@ Complete this section only if you selected Infobip. Infobip owns the WhatsApp Bu ## Artemis channel configuration -Create the connection before you register the webhook with your provider. Provider callbacks can arrive as soon as you save the webhook, and the runtime has to resolve an inbound sender to a saved connection before it can authenticate the event. +Create the connection before you register the webhook with your provider. Callbacks can arrive as soon as you save the webhook, and the runtime has to resolve an inbound sender to a saved, active connection before it can authenticate the event. 1. Open Artemis and select the project. -2. Go to **Deployments** -> **Channels** -> **WhatsApp** -> **+ New**. The **New WhatsApp Connection** dialog opens. -3. Configure the fields that apply whichever provider you chose: +2. Go to **Deployments** -> **Channels** -> **WhatsApp** -> **+ New**. The **New WhatsApp Connection** dialog opens, with the setup guide on the left and the connection fields on the right. +3. Set **Provider** first. The guide, the field set, and the label of the routing identifier field all change to match. The routing identifier field sits above **Provider**, so recheck it after you switch providers. +4. Configure the fields that apply to every provider: | 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 sender and the environment it serves, because a project can hold several WhatsApp connections. Routing ignores this value. | - | Provider | Your chosen Business Solution Provider | Decides which credential fields the dialog shows and which webhook route you register later, so set it before you fill in anything below it. | - | Environment | Your published environments | The environment whose active deployment answers incoming messages. Leave the working copy default only while you develop, and bind the connection to an environment later from the **Deployment** tab. | - | Provider Verification Strength | Defaults to **Weak** | How far the runtime trusts the provider's identity assertion when it links a sender to an existing session. Choose **Strong** only when you trust the provider's assertions enough to base continuity and account-linking decisions on them. | - | Initial Status | Defaults to **Active** | 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. | + | **Display Name** | You choose it | The label operators see in the connections list. Name it for the sender and environment it serves, because a project can hold several WhatsApp connections. Routing ignores this value. | + | **Provider** | Your chosen BSP | Which credential fields the dialog shows, which webhook route the connection generates, and which setup guide appears. | + | **Environment** | Your published environments | The environment whose active deployment answers incoming messages. 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. | + | **Provider Verification Strength** | Defaults to **Weak** | How far the runtime trusts the provider's identity assertion when it links a sender to an existing session. Choose **Strong** only when you trust the provider's assertions enough to base continuity and account-linking decisions on them. | + | **Initial Status** | Defaults to **Active** | Whether the connection handles messages. **Active** takes traffic immediately. **Inactive** saves the connection in a disabled state until you activate it, which suits staging ahead of a launch. | -4. Configure the routing identifier and credential fields, which change with the provider: +5. Configure the routing identifier and credential fields for your provider: | Artemis connection field | Source / Notes | What it controls | |---|---|---| - | Phone Number ID | **WhatsApp** -> **API Setup**, below the test phone number | Routes inbound messages to this connection. The runtime matches the sender identifier on each callback to this value, so a wrong entry here produces a connection-not-found result rather than an authentication error. | - | Access Token | **WhatsApp** -> **API Setup**, or a system user token for production | Authenticates every outbound message Artemis sends. | - | Phone Number ID | Same value as the routing identifier | Identifies the sender on outbound messages. | - | App Secret | **App settings** -> **Basic** | Verifies the signature Meta puts on each inbound callback. Without it, Artemis can't confirm that a callback came from Meta. | - | Verify Token | You invent it | Meta echoes it during the webhook handshake, and Artemis compares the two. | + | **Phone Number ID** (routing identifier) | **WhatsApp** -> **API Setup**, below the test phone number | Routes inbound messages to this connection by matching `metadata.phone_number_id`. A wrong entry produces connection-not-found rather than an authentication error. | + | **Access Token** | **WhatsApp** -> **API Setup** for testing. A system user token for production. | Authorizes every outbound Graph API call. Use a least-privilege system user token and never expose it in client code. | + | **Phone Number ID** (credential) | Same value as the routing identifier | Identifies the sender on outbound messages. | + | **App Secret** | **App settings** -> **Basic** | Verifies the HMAC signature Meta puts on each inbound POST. | + | **Verify Token** | You invent it | Meta echoes it during the webhook handshake, and the runtime uses it to find this connection and confirm the match. | - Meta Cloud API asks for the Phone Number ID twice, once as the routing identifier and once as an outbound credential. Enter the same value in both. Other providers use different values in each field, which is why they stay separate. + Meta Cloud API asks for the Phone Number ID twice: once as the external identifier that routes inbound events, and once as the credential for outbound delivery. Paste the same value into both. Other providers use different values in each role, which is why the fields stay separate. | Artemis connection field | Source / Notes | What it controls | |---|---|---| - | WhatsApp Phone Number | **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders** | Routes inbound messages to this connection. Enter the sender number as digits only, because a stray plus sign or space produces a connection-not-found result. | - | Authentication Method | Matches how your Infobip account is set up | Whether Artemis authenticates with an API key or with a username and password. | - | API Base URL | The Infobip homepage, in the form `xxxxx.api.infobip.com` | Your account's personalized host, entered with the `https://` scheme. Requests to the wrong base URL take a suboptimal route or fail outright. | - | API Key | **Developer Tools** -> **API Keys** | The key Artemis sends on every outbound call to Infobip. The dialog shows credential fields for basic authentication instead when you select that method. | + | **WhatsApp Phone Number** | **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders** | Routes inbound messages by matching `results[0].to`. Enter digits only. The runtime tolerates a leading plus and normalizes the inbound value, but any other formatting or a different number produces connection-not-found. | + | **Authentication Method** | Matches how your Infobip account authenticates | Whether Artemis sends an API key or a username and password, and which credential fields appear below. | + | **API Base URL** | The Infobip homepage, in the form `xxxxx.api.infobip.com` | Your account's personalized host, entered with the `https://` scheme. The wrong base URL takes a suboptimal route or fails outright. | + | **API Key**, or username and password | **Developer Tools** -> **API Keys**, or your account's basic credentials | The credential Artemis builds into the authorization header of every outbound call. Fill in only the method you selected. | + + Infobip inbound requests aren't cryptographically verified. Don't select **Strong** for **Provider Verification Strength** unless your deployment adds and validates a trusted identity assertion before traffic reaches the runtime. + + + + | Artemis connection field | Source / Notes | What it controls | + |---|---|---| + | **WhatsApp Business Phone Number** | The business number Gupshup provisioned, digits only | Routes inbound messages by matching `body.waNumber`. Entering the customer's number from `body.mobile` produces connection-not-found. | + | **API Username** | Your Gupshup Enterprise user ID | Authenticates outbound Gateway API calls, together with the password. | + | **API Password** | Your Gupshup Enterprise password | Authenticates outbound Gateway API calls. Keep it server-side only. | + | **Webhook JWT Secret** (optional) | The secret shared with whoever signs inbound tokens | Validates the bearer JWT on inbound callbacks, HS256 by default. Leave it blank to skip cryptographic verification. | - Infobip doesn't sign its callbacks with a shared secret the way Meta does, so Artemis verifies inbound traffic by source network. Confirm with your Infobip contact which addresses their platform sends from, and allowlist those before you go live. + A saved Webhook JWT Secret helps only if the inbound bearer token carries a signature made with the same secret. Send a real callback after you set it, and confirm the runtime accepts it. -5. Select **Create**. -6. Open the connection and copy the **Webhook URL** from the **Overview** tab. The URL carries the route for the provider you selected, so copy it rather than constructing it. If the dialog reports that the runtime URL is unavailable, configure Runtime first, then reopen the connection. +6. Select **Create**. +7. Open the connection and copy the **Webhook URL** from the summary panel on the right, or from the **Configuration** tab. The URL already carries your provider's route, so copy it rather than building it by hand. If the dialog reports that the Runtime URL is unavailable, configure Runtime first, then reopen the connection to get the complete URL. --- ## Webhook configuration with your provider -The webhook is what turns a one-way integration into a conversation. Until your provider has a callback URL, your agent can send but never receives. +The webhook turns a one-way integration into a conversation. Until your provider has the callback URL, your agent can send but never receives. In your Meta app, go to **WhatsApp** -> **Configuration** in the left menu. The **Webhook** row sits at the top of this screen. - 1. Select **Edit**. Meta opens a dialog with two fields. - 2. Paste the Artemis **Webhook URL** into the callback URL field, and the same **Verify Token** you entered in Artemis into the verify token field. - 3. Select **Verify and save**. Meta immediately calls the URL with a challenge and expects your verify token back, so the dialog stays open with an error when the handshake fails. A dialog that closes means the URL verified. - 4. Below the webhook row, find the webhook fields list, select **Manage**, and subscribe to the **messages** field. + 1. Confirm the Artemis connection exists and is **Active**. The runtime answers Meta's handshake only for a saved connection. + 2. Select **Edit**. Meta opens a dialog with two fields. + 3. Paste the Artemis **Webhook URL** into the callback URL field, and the same **Verify Token** you saved in Artemis into the verify token field. + 4. Select **Verify and save**. Meta sends a GET challenge to the URL. The runtime finds the connection by its Verify Token and returns `hub.challenge` only when the token matches. A dialog that closes means the URL verified. A dialog that stays open with an error means the handshake failed. + 5. Below the webhook row, find the webhook fields list, select **Manage**, and subscribe to the **messages** field. + 6. Confirm the right WhatsApp Business Account and phone number attach to this app. + + Verification alone delivers nothing. Meta verifies the URL whether or not you subscribe to anything, so a verified webhook with no subscription looks correct on screen and still sends your agent no traffic. Check the subscription first when the setup looks right and nothing arrives. - Verification alone delivers nothing. Meta verifies the URL whether or not you subscribe to anything, so a verified webhook with no subscription looks correct on screen and still sends your agent no traffic. Check this first when the setup looks right and nothing arrives. + Use the generic route exactly as the connection shows it. The runtime extracts `metadata.phone_number_id` from each signed POST body, so don't append the phone number or a provider slug. In the Infobip web interface, go to **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders**. - 1. Find the tile for your sender and open its three-dot menu. - 2. Select **Edit configuration**. - 3. Turn on forwarding to a URL, which Infobip labels as forwarding to HTTP in some accounts, and paste the Artemis **Webhook URL** into the URL field. - 4. Select **Save**. + 1. Confirm the Artemis connection exists and is **Active**. + 2. Find the tile for your sender and open its three-dot menu. + 3. Select **Edit configuration**. + 4. Turn on forwarding to a URL, which some accounts label as forwarding to HTTP, and paste the Artemis **Webhook URL** into the URL field. + 5. Select JSON delivery, and include every message type the agent must receive. + 6. Select **Save**. + 7. Send a test event from the portal if your account offers one, or send a real message, and require an HTTP 2xx delivery result. - Infobip has no verification handshake, so saving the configuration is the whole registration. Infobip documents what arrives on that URL under [inbound messages](https://www.infobip.com/docs/whatsapp/message-types-and-templates/inbound-messages). Nothing confirms the URL works until a real message arrives, which makes the test in the next section the only proof you have. + Infobip has no verification handshake, so saving the configuration is the whole registration. Infobip documents what arrives on that URL under [inbound messages](https://www.infobip.com/docs/whatsapp/message-types-and-templates/inbound-messages). + + The URL must contain `/whatsapp/infobip/webhook`. The generic Meta route expects a different payload and a different verification model. Keep delivery reports on a separate destination: don't point delivery-report payloads at the message webhook unless your Infobip configuration explicitly uses the same schema. Configuration lives on the sender rather than on the account, so a second sender needs its own forwarding configuration and its own Artemis connection. + + + Gupshup sets the inbound callback per account. Depending on your account, you set it in the account's webhook or callback settings, or your Gupshup account manager sets it for you. + + 1. Confirm the Artemis connection exists and is **Active**. + 2. Open the WhatsApp account's webhook or callback settings and paste the Artemis **Webhook URL** as the inbound message callback. If your account doesn't expose these settings, send the URL to your Gupshup account manager and ask them to set it as the inbound callback. + 3. Enable the inbound events the agent needs: text, media, location, contacts, and interactive replies. Save the callback configuration. + 4. If you set a Webhook JWT Secret, send a real callback that carries `Authorization: Bearer` with a matching HS256 token. The runtime rejects a missing, malformed, expired, or incorrectly signed token. + + The URL must contain `/whatsapp/gupshup/webhook`. The runtime routes from `body.waNumber`, so don't append the phone number to the path. + + Gupshup typically allows one inbound callback URL per Enterprise account. Use a separate Gupshup account for each environment you want to keep apart, since one account can't point at two connections. + ### Validation checklist +Work down this list once per connection. Each row depends on the one above it. + | Validation item | Expected result | |:---|:---| | Choose a provider | The provider selected in Artemis matches the account where the sender lives. | -| Complete provider setup | Meta: app created, WhatsApp product added, test recipient verified. Infobip: sender available, base URL and API key collected. | +| Complete provider setup | Meta: app created, WhatsApp product added, test recipient verified. Infobip: sender live, base URL and one credential method collected, network controls planned. Gupshup: Enterprise account confirmed, business number and API credentials collected. | | Collect credentials | Routing identifier and credentials copied from the same provider account. | | Create the Artemis connection | Connection saved as **Active** with the provider's fields and the intended environment. | -| Register the callback URL | Meta: the webhook dialog closes after **Verify and save**. Infobip: forwarding is on for that sender. | -| Subscribe the events | Meta only: the webhook subscribes to the **messages** field. | +| Register the callback URL | Meta: the webhook dialog closes after **Verify and save**. Infobip: JSON forwarding is on for that sender and a test returns 2xx. Gupshup: the inbound callback points at the Gupshup route. | +| Subscribe the events | Meta: the webhook subscribes to **messages**. Infobip: every needed message type forwards. Gupshup: inbound message events are on. | | Send a live message | A real WhatsApp conversation produces exactly one agent reply. See [Verify the connection](#verify-the-connection). | ## Verify the connection Artemis doesn't synthesize provider callbacks, so a real WhatsApp message is the only way to confirm the integration works end to end. -1. From a WhatsApp account you registered as a test recipient, send the business sender a short message you can search for later. A distinctive string makes the message easy to find in session records. -2. Check that the agent replies once, from the intended sender and the intended environment. Duplicate replies point to duplicate provider subscriptions, another automation on the same number, or repeated webhook delivery rather than an agent fault. -3. If no reply arrives, open **Sessions** and search for the message you sent. A session that exists tells you the webhook works and the outbound path failed, while no session tells you nothing reached the runtime at all. The two need different fixes, so make this check before you change any configuration. -4. If the agent sends buttons or lists, select a button and a list row and confirm the action returns to the same session. WhatsApp limits how many reply buttons a message carries and how long their labels run, so check that your authored content renders in WhatsApp rather than only in preview. -5. Test only the message types your provider enables, then confirm the agent handles the downloaded attachment rather than only acknowledging it. +1. Use an approved test recipient. On a Meta app in development mode or a provider sandbox, register the number first. For production, confirm business verification, sender quality, payment, and template approvals are complete. +2. From a normal WhatsApp account, send the business sender a short, distinctive message you can search for later. +3. Check that the agent replies once, from the intended sender and the intended environment. Duplicate replies point to duplicate provider subscriptions, another automation on the same number, or repeated webhook delivery rather than an agent fault. +4. If no reply arrives, open **Sessions** and search for the message you sent. A session tells you the webhook works and the outbound path failed. No session tells you nothing reached the runtime. The two need different fixes, so make this check before you change any configuration. +5. If the agent sends buttons or lists, select a button and a list row and confirm the action returns to the same session. WhatsApp limits how many reply buttons a message carries and how long their labels run, so check that your content renders in WhatsApp rather than only in preview. +6. Exercise every message type your provider enables, and confirm the agent handles the downloaded attachment rather than only acknowledging it. + +The runtime normalizes these WhatsApp inputs across all three providers. Test only the ones your provider enables for your sender. + +| Message type | What to confirm | +|---|---| +| `text` | The agent receives and answers it. | +| `image`, `video`, `audio`, `document` | The runtime downloads the file and the agent processes its content. | +| `location`, `contacts` | The agent reads the shared data rather than ignoring it. | +| `interactive replies` | A button or list selection returns to the same session with the right action. | A webhook that returns 2xx proves only that your provider reached the runtime. It says nothing about whether your outbound credentials work. Always confirm a real two-way conversation before you call the channel done. --- +## Security and provider boundaries + +Each provider protects a different part of the exchange. These rules keep the inbound and outbound halves trustworthy. + +| Provider | Inbound protection | Outbound protection | +|---|---|---| +| **Meta Cloud API** | Every POST must carry `X-Hub-Signature-256`. The runtime computes HMAC-SHA256 over the unchanged raw body with your App Secret. | The Access Token authorizes outbound Graph API calls. Use a least-privilege system user token and never expose it in client code. | +| **Infobip** | Network-based only. There's no request-signature check, so restrict ingress with provider IP allowlists, a trusted gateway, and network controls. | The API key or basic credentials authorize outbound calls and live only in encrypted Artemis fields. Never treat the API key as webhook authentication. | +| **Gupshup** | When configured, the Webhook JWT Secret validates the bearer JWT with an allowed HMAC algorithm. Without it, rely on network controls. | The API username and password authorize outbound Gateway API calls and must stay server-side. | + +These rules apply to every provider: + +- **Preserve the raw body**: Where a provider signs the body, any proxy or middleware in front of Artemis must pass the exact raw bytes through. Re-serializing JSON breaks the signature and fails every callback. +- **Rotate in the right order**: Rotate credentials without changing the inbound sender identifier. Update Artemis first, then revoke the old credential, then verify both inbound and outbound traffic. +- **Separate environments completely**: Use separate apps or senders, credentials, webhooks, and connections for development and production. +- **Match verification strength to evidence**: Keep **Provider Verification Strength** at **Weak** unless the provider's identity assertion carries cryptographic proof, or your deployment adds and validates one. + +--- + ## Create a permanent access token -This section applies to Meta Cloud API only. Infobip API keys don't expire on a schedule, so rotate them on your own policy instead. +This section applies to Meta Cloud API only. Infobip API keys and Gupshup passwords don't expire on a schedule, so rotate them on your own policy instead. -The token on the API Setup page expires within 24 hours, which is enough to test and not enough to run. Replace it with a system user token, which lasts until you revoke it. Meta explains how the token types differ under [access tokens](https://developers.facebook.com/docs/whatsapp/access-tokens). +The token on the API Setup page expires within 24 hours. Replace it with a system user token, which lasts until you revoke it. Meta explains how the token types differ under [access tokens](https://developers.facebook.com/docs/whatsapp/access-tokens). This work happens in Meta Business Suite rather than the App Dashboard, and it needs a Meta Business admin. @@ -276,9 +443,9 @@ This work happens in Meta Business Suite rather than the App Dashboard, and it n 1. Select **Generate token**, choose your app, and set the expiration to never. - 2. Select the `whatsapp_business_messaging` permission so the token can send and receive messages, and `whatsapp_business_management` so it can manage templates and account settings. + 2. Select the `whatsapp_business_messaging` permission so the token can send and receive messages, and `whatsapp_business_management` so it can manage templates and account settings. Grant nothing beyond what the integration uses. 3. Generate the token and copy it straight into your secret manager, because Meta displays it once and never again. - 4. Update the **Access Token** on the Artemis connection from the **Credentials** tab. + 4. Update the **Access Token** on the Artemis connection from the **Credentials** tab, then revoke the temporary token. @@ -286,72 +453,78 @@ This work happens in Meta Business Suite rather than the App Dashboard, and it n ## Move to production -A test sender covers development and nothing else. Who does the production paperwork depends on your provider. +A test sender covers development and nothing else. Who does the production paperwork depends on your provider, and every path waits on Meta review. -On Meta Cloud API, you complete business verification, add a payment method, register a business phone number in WhatsApp Manager, and get your display name approved. You do all of this from [Meta Business Suite](https://business.facebook.com/). On Infobip, Infobip runs the sender registration and verification for you, and you supply the business details it asks for. Either way the work waits on Meta review, so start it well ahead of your launch date. +| Provider | Who does the production work | +|---|---| +| **Meta Cloud API** | You complete business verification, add a payment method, register a business phone number in WhatsApp Manager, and get your display name approved, all from [Meta Business Suite](https://business.facebook.com/). | +| **Infobip** | Infobip runs sender registration and Meta verification. You supply the business details it asks for. | +| **Gupshup** | Gupshup creates the Enterprise account and onboards the WhatsApp business number with Meta. You supply the business details it asks for. | Two WhatsApp rules shape what your agent can say, whichever provider carries the traffic: **The customer service window.** After a customer messages you, you can reply freely for 24 hours. Outside that window, an outbound message needs an approved template, so an agent that reaches out first needs templates approved before it can start a conversation at all. Template approval is its own review, and a rejected template blocks the conversation you wrote it for. -**Separate senders per environment.** Use different senders, credentials, webhooks, and connections for development and production. Sharing a sender means test traffic reaches the same conversation history as customer traffic. +**Separate senders per environment.** Use different senders, credentials, webhooks, and connections for development and production. Sharing a sender means test traffic lands in the same conversation history as customer traffic. --- ## Manage the channel connection -Opening a WhatsApp connection from **Deployments** -> **Channels** shows four tabs. The header carries the connection name, its environment, its status, and a delete control. +Open a WhatsApp connection from **Deployments** -> **Channels** -> **WhatsApp** to manage it. The page has a header, three tabs, and a summary panel on the right. - - - **Connection Summary** records what the connection is and when it changed. +**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** below the summary carries the values you need on the provider side, each with a copy control. +**Summary panel.** Stays visible on every tab and carries the values you need on the provider side. - | Value | Description | - |---|---| - | **Webhook URL** | The callback URL to register with your provider. It already carries the provider route, so copy it rather than building it by hand. | - | Routing identifier | The value this connection matches inbound messages to, shown as the Phone Number ID or the WhatsApp phone number depending on your provider. Check it here first when messages arrive and no session appears. | - +| Field | Description | +|---|---| +| **Channel** | Reads **WhatsApp**. | +| **Connection Type** | Reads **Channel Connection**. | +| **Identifier** | The routing identifier this connection matches inbound messages to: the Phone Number ID or the WhatsApp number, depending on your provider. Check it first when messages arrive and no session appears. | +| **Credentials** | Reads **Configured** once credentials save. | +| **Webhook URL** | The callback URL to register with your provider, with a copy control. It already carries the provider route. | +| **Created** and **Updated** | Date and time of creation and of the last change. | + The platform encrypts credentials after you save them, so every field reads as saved rather than showing its value. Leave a field empty to keep the current value, or enter a new value to replace it. - The fields below the first one change with your provider. Meta Cloud API shows the access token, Phone Number ID, App Secret, and Verify Token. Infobip shows the authentication method, API base URL, and either an API key or basic authentication credentials. - | Field | Description | |---|---| | **Use Auth Profile** | Switches the connection to a saved auth profile in place of the fields below. Prefer it when the same credentials serve more than one connection, since a rotation then touches one profile. | - | Outbound credential | Authenticates outbound messages. Replace it here when you rotate a Meta token or an Infobip API key. | - | Inbound verification | Confirms that a callback came from your provider. Changing the Verify Token here breaks the Meta webhook until you change it in Meta as well. | + | Outbound credentials | Meta: **Access Token** and **Phone Number ID**. Infobip: authentication method, **API Base URL**, and an API key or basic credentials. Gupshup: **API Username** and **API Password**. Replace them here when you rotate. | + | Inbound verification | Meta: **App Secret** and **Verify Token**. Gupshup: **Webhook JWT Secret**. Changing the Meta Verify Token breaks the webhook until you change it in Meta as well. | - Select **Save Credentials** to apply your changes. + Select **Save Credentials** to apply your changes. Update credentials here before you revoke the old ones at the provider. - Under **General**, update the **Display Name** and the **Provider Verification Strength**. - - Under **WhatsApp Settings**, the routing identifier appears read-only. You can't change it after creation, so a connection pointed at the wrong sender needs replacing rather than editing. + This tab carries the connection's editable settings and a second copy of the webhook URL. - **Authorization message** + | Setting | Description | + |---|---| + | **Display Name** | The label operators see in the connections list. | + | **Provider Verification Strength** | Under **WhatsApp Settings**. How far the runtime trusts the provider's identity assertion. | + | Routing identifier | Under **WhatsApp Settings**, read-only with a copy control. You can't change it after creation, so a connection pointed at the wrong sender needs replacing rather than editing. | + | **Authorization message** | The **Message template** the connection sends when a tool needs the user to authorize before the conversation continues. | + | **Webhook URL** | The callback URL, with a copy control. | - The connection sends this message when a tool needs the user to authorize before the conversation continues. Edit the template to match your agent's voice, since the default reads as system text rather than as the agent talking. + The default authorization message reads as system text. Edit the template to match your agent's voice, insert variables from the chips below the editor, and select **Show more** to see every variable. Select **Show preview** to check the rendered message. - The editor lists the variables you can insert, offers a preview, and expands to show every available variable. The variables cover the number of outstanding authorizations, the profile each one belongs to, and the link the user follows. + | Variable | What it inserts | + |---|---| + | `{{remaining}}` | The number of authorizations still outstanding. | + | `{{#authorizations}}` ... `{{/authorizations}}` | A block that repeats once per outstanding authorization. | + | `{{index}}`, `{{profileName}}`, `{{authLink}}` | Inside the block: the item's position, the auth profile it belongs to, and the link the user follows. | Select **Save Changes** to apply your changes. - **Agent Version** carries an **Environment** dropdown that selects which deployed version handles incoming messages. + This tab decides which deployed agent version answers the channel. + + **Environment Binding** carries an **Environment** dropdown that 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. @@ -363,26 +536,36 @@ Opening a WhatsApp connection from **Deployments** -> **Channels** shows four ta ## Key values reference -Each value sits on a different provider screen, and two of them look alike enough to swap by accident. Use the table for your provider to collect everything in one pass. +Each value sits on a different provider screen, and several look alike enough to swap by accident. Use the table for your provider to collect everything in one pass. | Value | Where to find it | Where it goes | | ----- | ---------------- | ------------- | - | **Phone Number ID** | **WhatsApp** -> **API Setup**, directly below the test business phone number | The routing identifier and the outbound credential field in Artemis | + | **Phone Number ID** | **WhatsApp** -> **API Setup**, directly below the test business phone number | The routing identifier and the Phone Number ID credential in Artemis | | **Access Token** | **WhatsApp** -> **API Setup** for testing. For production, **Business settings** -> **Users** -> **System users** in Meta Business Suite | The **Access Token** field in Artemis | | **App Secret** | **App settings** -> **Basic**, revealed by selecting **Show** | The **App Secret** field in Artemis | | **Verify Token** | You choose it | The **Verify Token** field in Artemis, and the webhook configuration in Meta | - | **Webhook URL** | The **Overview** tab of the Artemis connection | The callback URL in **WhatsApp** -> **Configuration** in the Meta app | + | **Webhook URL** | The summary panel or **Configuration** tab of the Artemis connection | The callback URL in **WhatsApp** -> **Configuration** in the Meta app | | Value | Where to find it | Where it goes | | ----- | ---------------- | ------------- | - | Sender number | **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders** | The **WhatsApp Phone Number** field in Artemis, as digits only | + | Sender number | **Channels and Numbers** -> **Channels** -> **WhatsApp** -> **Senders** | The **WhatsApp Phone Number** field in Artemis, as digits | | **API Base URL** | The homepage of the Infobip web interface, in the form `xxxxx.api.infobip.com` | The **API Base URL** field in Artemis, with the `https://` scheme | - | **API Key** | **Developer Tools** -> **API Keys** | The **API Key** field in Artemis | - | **Webhook URL** | The **Overview** tab of the Artemis connection | The forwarding URL in the sender's **Edit configuration** screen | + | **API Key** or basic credentials | **Developer Tools** -> **API Keys**, or your account's username and password | The matching credential fields in Artemis | + | Source addresses | Your Infobip contact | Your allowlist or gateway in front of the Artemis route | + | **Webhook URL** | The summary panel or **Configuration** tab of the Artemis connection | The forwarding URL in the sender's **Edit configuration** screen | + + + + | Value | Where to find it | Where it goes | + | ----- | ---------------- | ------------- | + | WhatsApp business number | Your Gupshup Enterprise account, the number Gupshup sends as `body.waNumber` | The **WhatsApp Business Phone Number** field in Artemis, as digits | + | User ID and password | Issued with your Gupshup Enterprise account | The **API Username** and **API Password** fields in Artemis | + | JWT secret | Agreed with whoever signs inbound tokens | The **Webhook JWT Secret** field in Artemis, if you use it | + | **Webhook URL** | The summary panel or **Configuration** tab of the Artemis connection | The inbound callback in Gupshup, set by you or your account manager | @@ -390,17 +573,24 @@ Each value sits on a different provider screen, and two of them look alike enoug ## Troubleshoot connection issues +Start with the **Sessions** check from [Verify the connection](#verify-the-connection), then match the symptom here. + | Symptom | Likely cause | Recommended action | |---|---|---| -| The agent never replies, and a session exists | The recipient isn't verified on a test sender | On Meta, development mode accepts inbound messages from anyone but delivers only to verified recipients, so add your number under **WhatsApp** -> **API Setup**. On an Infobip trial sender, verify the recipient number in Infobip. | -| The agent never replies, and no session exists | Nothing reached the runtime | On Meta, confirm the webhook subscribes to the `messages` field, that the callback URL verified, and that the App Secret matches. On Infobip, confirm forwarding is on for that sender and that the URL matches the connection. | -| The runtime reports no connection found | The routing identifier doesn't match the inbound callback | Compare the sender identifier on the inbound callback with the value saved in Artemis, and confirm the provider selector matches the provider that sent it. On Infobip, check for a plus sign or spaces in the saved number. | -| Inbound messages arrive but no reply goes out | The outbound credential is wrong or expired | Check the outbound credential, the sender identifier, the account-specific base URL where your provider uses one, the connection status, and whether a runnable deployment exists. A temporary Meta token that expired overnight produces exactly this symptom. | -| Inbound callbacks reach the runtime but fail verification | The inbound verification setting doesn't match the provider | On Meta, the App Secret doesn't match the app that sent the callback. On Infobip, your allowlist is missing the address their platform sent from. | -| Customers receive duplicate replies | More than one subscription or automation answers the same number | Remove duplicate provider subscriptions, disable any other automation on the number, and account for provider retry behavior. | -| Text works but buttons or lists fail | The content exceeds a provider limit, or the authored action is gone | Check the provider's limits, the reply payload IDs, whether your provider supports the interactive type, and how the agent handles the returned action. | -| Text works but media fails | The message type isn't enabled, or the file breaks a policy | Confirm the provider enabled that message type, the credentials can download media, size and host policies allow it, and the agent handles attachments. | -| Outbound sends fail outside the customer service window | The 24-hour window has closed | Send an approved WhatsApp template instead. | +| Meta webhook verification fails and the dialog stays open | The connection doesn't exist yet, the Verify Token doesn't match, or Meta can't reach the URL | Create the connection first, match the Verify Token exactly, use the generic callback URL, and confirm the GET request can reach public HTTPS. | +| Meta callbacks return 401 | App Secret mismatch, or the body changed before verification | Copy the App Secret from the same app that owns the sender, and make sure proxies and middleware pass the raw bytes unchanged. | +| Gupshup callbacks return 401 | The JWT setting doesn't match what Gupshup sends | Use the Gupshup-specific URL. Either leave **Webhook JWT Secret** blank, or make sure each callback carries a bearer JWT signed with the same secret and an allowed HMAC algorithm. | +| Infobip test delivery fails | Wrong route, payload format, sender, or source network | Use the Infobip-specific URL with JSON delivery, enter the sender as digits, allow Infobip's source addresses, and confirm the callback returns 2xx quickly. | +| The runtime reports no connection found | The routing identifier doesn't match the inbound callback | Compare the inbound sender field with the saved identifier: `metadata.phone_number_id` for Meta, `results[0].to` for Infobip, `body.waNumber` for Gupshup. Confirm the selected provider matches the one that sent it. | +| The agent never replies, and a session exists | The recipient isn't approved on a test sender | On Meta, add your number under **WhatsApp** -> **API Setup**, since development mode accepts inbound messages from anyone but delivers only to verified recipients. On a trial or sandbox sender, verify the recipient with the provider. | +| The agent never replies, and no session exists | Nothing reached the runtime, or verification rejected it | On Meta, confirm the **messages** subscription, the verified callback URL, and the App Secret. On Infobip, confirm forwarding is on for that sender. On Gupshup, confirm the inbound callback points at the Gupshup route. | +| Inbound messages arrive but no reply goes out | The outbound path fails | Check the outbound credential, the sender identifier, the account-specific base URL where your provider uses one, the connection status, and whether a runnable deployment exists. An expired temporary Meta token produces exactly this symptom. | +| Traffic stops right after a credential rotation | Someone revoked the old credential before Artemis had the new one | Enter the new credential in the **Credentials** tab, then verify inbound and outbound traffic. Next time, update Artemis before you revoke. | +| Infobip callbacks fail with unexpected payloads | Delivery reports reach the message webhook | Point delivery reports at a separate destination unless your Infobip configuration uses the same schema for both. | +| Customers receive duplicate replies | More than one subscription or automation answers the same number | Remove duplicate provider subscriptions, disable any other automation on the number, and account for provider retry and redelivery behavior. | +| Text works but buttons or lists fail | The content exceeds a provider limit, or the authored action is gone | Check the provider's limits, the reply payload IDs, whether your BSP supports the interactive type, and how the agent handles the returned action. | +| Text works but media fails | The message type isn't enabled, or the file breaks a policy | Confirm the BSP enabled that message type, the credentials can download media, size and host policies allow it, and the agent handles attachments. | +| Outbound sends fail outside the customer service window | The 24-hour window has closed | Send an approved WhatsApp template through the selected provider when its policy requires one. | --- @@ -426,6 +616,13 @@ Use these pages when you need detail beyond what this article covers. | [Base URL](https://www.infobip.com/docs/developer-resources/about-infobip-apis/base-url) | Why Infobip personalizes the base URL and what a wrong one does. | | [Developer resources](https://www.infobip.com/docs/developer-resources) | Authentication methods, API keys, and the wider API reference. | + + + | Resource | Use it for | + | -------- | ---------- | + | [Gupshup documentation](https://docs.gupshup.io/docs/overview) | The entry point to Gupshup's WhatsApp, Enterprise, and API documentation. | + | [API reference](https://docs.gupshup.io/docs/api-reference) | How the Enterprise Gateway API authenticates with a user ID and password. | + {{related}} diff --git a/agent-platform/context-and-prompts.mdx b/agent-platform/context-and-prompts.mdx new file mode 100644 index 000000000..cb8cb07b9 --- /dev/null +++ b/agent-platform/context-and-prompts.mdx @@ -0,0 +1,70 @@ +--- +title: How a turn is built +sidebarTitle: Context and prompts +--- + +Every agent turn ends in a single model request: one system prompt, the conversation history, and the tool list. This page explains which values the model can see each turn, where they come from, and how to keep a value out of the prompt entirely. For how that request is kept small -- the size budgets and compaction policies -- see [Context size, compaction, and budgets](/agent-platform/context-compaction). + +## At a glance + +Before the model reads it, every source of context is shaped: memory and `## Current Context` by visibility rules and size limits, conversation history and tool results by compaction, and knowledge-base results by a token budget. Guardrails check what goes into and comes out of each call, but they never see the assembled prompt itself. + +## What the model sees each turn + +Session values reach the system prompt in two ways: through the memory sections an agent declares (`## Session Memory`, `## Granted Memory`, and similar), and through a `## Current Context` block. Which values land in `## Current Context` depends on the agent's visibility mode. + +| Mode | When it applies | What goes into `## Current Context` | +|------|------------------|---------------------------------------| +| Allow-list (default) | The agent does not declare `BEHAVIOR:` with `role:` | Values the agent's own `GOAL`, `PERSONA`, `LIMITATIONS`, or `SYSTEM_PROMPT` reference; values passed in on handoff; results of the agent's own tools; values granted by `FLOW` steps. If any of those texts uses `{{context}}`, every session value is admitted. | +| Explicit | The agent declares `BEHAVIOR:` with `role: router`, `orchestrator`, or `assistant` | Only declared session memory, execution-tree memory, memory granted on handoff, and interaction details such as language, locale, and timezone. Undeclared and persistent values never appear. | + +These values are never shown in `## Current Context`, in either mode: + +- Platform identifiers -- session, tenant, project, and user IDs -- plus raw input and message metadata. +- The `config` and `env` namespaces. +- Keys that start with an underscore, except the handoff summary. +- Knowledge-base search results. They reach the model through the search tool call instead -- see [Knowledge base retrieval](/agent-platform/knowledge#how-the-platform-searches). +- In allow-list mode, values already shown in a memory section. In explicit mode, a declared session value can appear in both a memory section and `## Current Context`, so budget for that when sizing prompts. + +Tool results are visible only to the agent that produced them. A `last__result` value appears in the prompt of the agent that called the tool -- see [Store result](/agent-platform/abl-reference/tools#store-result). After a handoff, the receiving agent does not see it unless it's listed in `pass` or referenced directly. + +### Size limits + +Each `## Current Context` value is limited to 8,000 characters by default, and the whole block to 24,000. Automatic tool-result values are limited to 4,000 characters. A value over its limit is replaced by a marker object holding a preview of its start. Declared memory sections (`## Session Memory` and similar) are not size-limited, so keep declared memory small. The full set of default budgets, the voice-profile overrides, and how to diagnose a bloated or truncated prompt in a trace live in [Context size, compaction, and budgets](/agent-platform/context-compaction). + +### Keeping a value out of the prompt + +To keep a value out of what the model reads: + +- Don't declare it in `MEMORY:` and don't reference it. An allow-list agent never sees an undeclared value it doesn't reference. +- If a tool needs the value, declare it as a runtime-supplied parameter the model can't see. +- For tool results, use the tool's `MODEL_CONTEXT` to pass the model only the fields it needs -- see [MODEL_CONTEXT on a tool result](/agent-platform/abl-reference/tools#model_context-on-a-tool-result). + +```yaml +TOOLS: + use_runtime_state(runtime_state: string, operation: string) -> object + params: + runtime_state: + default_source: runtime + visibility_model: false + visibility_trace: false + context_access: + read: [runtime_state] +``` + +### Referencing values in prompt text + +Use `{{customer_tier}}` in `GOAL`, not `{{context.customer_tier}}`. In `GOAL`, `PERSONA`, and `LIMITATIONS`, the `context.` form makes the value visible in `## Current Context`, but the placeholder itself is not filled in -- only the plain `{{var}}` form interpolates. + +If a referenced value is unset, the literal `{{customer_tier}}` text stays in the prompt. Word the sentence so an empty value still reads sensibly, or set a default with `INITIAL:`. + +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. + +--- + +{{related}} + +- [Context size, compaction, and budgets](/agent-platform/context-compaction) -- default size budgets, where context grows, and how to debug a bloated prompt from a trace. +- [Agent declaration](/agent-platform/abl-reference/agent-declaration) -- `GOAL`, `PERSONA`, `LIMITATIONS`, and `SYSTEM_PROMPT:` syntax. +- [Memory and state](/agent-platform/memory-and-state) -- declaring session and persistent memory. +- [Tools](/agent-platform/abl-reference/tools) -- shaping and storing tool results. diff --git a/agent-platform/context-compaction.mdx b/agent-platform/context-compaction.mdx new file mode 100644 index 000000000..ec5607602 --- /dev/null +++ b/agent-platform/context-compaction.mdx @@ -0,0 +1,150 @@ +--- +title: Context size, compaction, and budgets +sidebarTitle: Compaction and budgets +--- + +As a conversation runs, the model's context keeps growing: more customer turns, more agent replies, more tool calls and results. The runtime automatically manages that context so it stays within model limits -- compressing large tool results, replacing older tool results with placeholders, and shortening earlier turns -- according to a set of compaction policies you can tune per agent, per project, or per tool. This page lists the default budgets, shows where to set them, and walks through diagnosing a prompt that's grown too large. + +For what actually determines *which* values reach the model in the first place -- visibility modes and `## Current Context` -- see [How a turn is built](/agent-platform/context-and-prompts). + +## Size limits and compaction + +Three policies set how much the model reads on a given turn: + +- `tool_results` -- how tool output is shaped, both this turn and on later turns. +- `prior_turns` -- how earlier turns in the conversation history are compacted. +- `prompt_context` -- how `## Current Context` values are sized and projected. + +They merge in this order: platform defaults, then the voice low-latency profile (voice channels only), then project settings, then the agent's `EXECUTION.compaction`, then per-tool hints. Nothing trims the conversation to a token budget automatically, so a long-running conversation keeps growing unless you set bounds. + +### Default values + +| Policy | Setting | Default | Voice latency profile | +|------------------|------------------------------------|-------------------------|-----------------------| +| `tool_results` | `strategy` | `summarize` | `structured` | +| | `max_chars` | 102,400 | 16,000 | +| | `structured_threshold` | 10,000 | 4,000 | +| | `keep_recent` | 2 | 1 | +| | `max_description_length` | 200 | 80 | +| | `summary_timeout_ms` | 5,000 (1,000 to 30,000) | 1,500 | +| `prior_turns` | `strategy` | `compact` | `compact` | +| | `assistant_preview_chars` | 200 | 120 | +| `prompt_context` | `value_max_chars` | 8,000 (40,000 max) | 6,000 | +| | `total_max_chars` | 24,000 (100,000 max) | 16,000 | +| | `auto_tool_result_value_max_chars` | 4,000 | 2,000 | +| | `projection_strategy` | `preview` | `preview` | + +### Prior-turn strategies + +| Strategy | Effect on earlier turns | +|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `none` | Earlier replies are kept as written. Tool results in history are still placeholders. | +| `placeholder` | Each earlier tool result is replaced by `[Prior turn result — summarized]`. | +| `compact` (default) | As `placeholder`, and each reply that followed a tool result is shortened to `assistant_preview_chars`. The agent's latest reply is kept whole if it is 2,000 characters or less. | +| `summarize` | Behaves the same as `compact`. No model call is made for this strategy. | + +### Projection strategies for Current Context + +A `## Current Context` value over its limit is replaced by a marker object (`_contextLimited: true`) carrying its original type and size, plus one of three levels of detail: + +- `preview` (the default) -- the first part of the value, as text. +- `summary` -- the value's shape: types, lengths, key names, and up to three sample items. +- `metadata` -- type and size only. + +### Where to set compaction policies + +- **Per agent, in ABL** -- the `EXECUTION.compaction` block. See [Compaction policy overrides](/agent-platform/abl-reference/agent-declaration#compaction-policy-overrides) for the full property reference. +- **Per project** -- the project runtime configuration, set by API or project import. Studio's Runtime Config tab exposes these controls only for the voice latency profile overrides; the project-wide section is not editable from Studio. +- **Per tool** -- `compaction: essential_fields`, `summary_timeout_ms`, and, for knowledge bases, `max_search_tokens`. See [Result compaction](/agent-platform/abl-reference/tools#result-compaction). + +```yaml expandable=true +EXECUTION: + models: + summarization: gpt-4.1-mini + compaction: + tool_results: + strategy: summarize + max_chars: 32000 + structured_threshold: 8000 + keep_recent: 2 + essential_fields: + search_orders: [id, status, total, createdAt] + summarize_prompt: "Keep order IDs, totals and statuses." + prior_turns: + strategy: compact + assistant_preview_chars: 300 + prompt_context: + value_max_chars: 8000 + total_max_chars: 24000 + auto_tool_result_value_max_chars: 4000 + projection_strategy: preview +``` + +The compaction policy is resolved once per conversation. In a multi-agent project, set compaction at the project level, or set it the same way on every agent in a handoff chain -- it is not re-resolved on handoff. + +Memory sections (`## Session Memory`, `## Granted Memory`, `## Gather Progress`) are not covered by these limits. Keep declared memory small -- see [Memory and state](/agent-platform/memory-and-state). For a single large tool result, a `MODEL_CONTEXT` view is a better tool than raising a size limit: it's exact, and it costs no extra model call. + +## Controlling context size + +You control three things: which values may enter the prompt, how large each piece may be, and how long tool output stays around. Most parts of the prompt have a default size limit you can change. Two parts have none -- the conversation history and declared session memory -- so uncontrolled growth usually starts there. Most cuts leave a marker you can find in a trace; knowledge-base chunk drops and the structural shortening of long lists before a summary do not. + +### Where context grows + +| Source | Grows with | Default limit | Your lever | +|--------|------------|----------------|-------------| +| Conversation history | Every turn | None: no token cap, and auto-summarization is off | `prior_turns` (previews of earlier replies), a response `MODEL_CONTEXT` on rich responses, `history: last_n` or `summary_only` on handoffs | +| Declared session memory (`## Session Memory`, `## Granted Memory`, `## Gather Progress`) | The size of the values you store | None | Declare only what the model needs. Keep large objects in tool results or persistent memory, and use `RESET: per_activation` for scratch values. | +| `## Current Context` | The number of values visible | 8,000 per value, 24,000 in total | Explicit visibility mode, named references instead of `{{context}}`, `prompt_context` budgets | +| Tool results, this turn | The size of the API payload | Summarized above 10,000 characters; 102,400 at most | `MODEL_CONTEXT` first, then the `tool_results` strategy and `essential_fields`. Avoid `strategy: none` on unbounded APIs. | +| Tool calls in history | Tool use per turn | Arguments kept for 6 rounds; results become a marker | Hide bulky arguments with `default_source: runtime` | +| Knowledge-base results | Chunk count and size | 40,000 tokens when more than 10 chunks come back | `max_search_tokens`, Top K, Similarity threshold -- see [Tool-level search settings](/agent-platform/knowledge#tool-level-search-settings) | +| Explicit mode | Each declared value | A value can appear in both `## Session Memory` and `## Current Context` | Keep declared memory small | +| Recall and notes | Cross-channel recall, resolved-intent ledgers, recall instructions | 30 messages of 500 characters each; 8 ledger entries | Recall settings; keep `INSTRUCTION` text short | + +### Where context gets cut + +| Cut point | Default | Marker in the trace | Lever | +|-----------|---------|----------------------|-------| +| One `## Current Context` value | 8,000 characters | `_contextLimited: true` with a preview, summary, or size | `value_max_chars` (up to 40,000), `projection_strategy` | +| The whole `## Current Context` block | 24,000 characters | Values left out are listed by name | `total_max_chars` (up to 100,000) | +| An earlier tool result in Current Context | 4,000 characters | `_contextLimited`, plus a `## Prior Tool Result Context` note | `auto_tool_result_value_max_chars` | +| A tool result this turn | Summarized above 10,000 characters; cut at 102,400 | `"_summarized": true` or `...[truncated: N chars, showing first M]` | `MODEL_CONTEXT`, `structured_threshold`, `max_chars`, `strategy` | +| An older result within a long turn | Only the last 2 rounds stay whole | `[Result available — see earlier in conversation]` | `keep_recent` | +| Tool results on later turns | Always replaced | `**COMPACTED FOR CHAT HISTORY**`, `[Prior turn result — summarized]` | Save what you need with `on_result: SET` | +| Earlier tool-backed replies | 200-character preview | `[Prior response: "…"]` | `assistant_preview_chars`, or `prior_turns: placeholder` | +| A `MODEL_CONTEXT` view | 16,000 characters or 1,000 items | An "unavailable" marker -- the view fails rather than being cut | Select fewer fields | +| Knowledge-base results | The token budget | Whole chunks dropped from the end | `max_search_tokens` | +| Handoff history | Full by default | The receiver's history starts later | `history:` -- see [History strategies](/agent-platform/abl-reference/multi-agent-and-supervisor#history-strategies) | + +### A budget recipe for a production agent + +1. Declare `BEHAVIOR: role:` so only declared and granted values reach `## Current Context`. +2. Give every tool with a large or nested result a `MODEL_CONTEXT`, and save the fields later turns need with `on_result: SET`. +3. Keep declared session memory to small scalars. Use `RESET:` for scratch values. +4. Use `history: last_n` or `summary_only` with a summary on handoffs in long conversations. Pass state with `pass`, not history. +5. Set `max_search_tokens` on every knowledge base, lower for voice. +6. Set compaction once at the project level so every agent in a handoff chain uses the same budgets, then tune each agent only where needed. +7. Run a 20-turn test conversation, then check the trace's Request view and the session Overview's Token Breakdown for growth from turn to turn. + +### Debugging a bloated or truncated prompt + +Open a session's Traces tab, pick an LLM step, and open its Request view (see [LLM step request and response](/agent-platform/sessions#llm-step-request-and-response)). Search `systemPrompt` and `messages` for `_contextLimited`, `truncated`, `_summarized`, `COMPACTED FOR CHAT HISTORY`, and `Prior response`. Also look for `Prior turn result`, `Result available`, and an "unavailable" marker. + +Knowledge-base results leave no marker in the trace, so compare their size against `max_search_tokens` directly. If the prompt is large and none of these markers explain it, the size is coming from conversation history or a memory section, and the levers in [Where context grows](#where-context-grows) apply. + +## Common mistakes + +- There is no per-entry switch to hide one declared memory value from the model. Either don't declare it, or supply it through a runtime-supplied tool parameter instead. +- There is no automatic token cap on conversation history. A long-running conversation needs `prior_turns`, `MODEL_CONTEXT`, and handoff history settings to stay bounded. +- Compaction settings are resolved once per conversation, the first time they're needed -- usually by the agent that starts it -- and are not refreshed on handoff. Set them consistently across a handoff chain instead of relying on the receiving agent's own settings. +- The automatic first knowledge-base search for a single-KB agent can't be turned off. Control its size with `max_search_tokens` instead. +- Studio's Runtime Config tab edits project compaction only inside the voice profile. Set the project-wide section by API or project import. + +--- + +{{related}} + +- [How a turn is built](/agent-platform/context-and-prompts) -- visibility modes and what reaches `## Current Context` in the first place. +- [Compaction policy overrides](/agent-platform/abl-reference/agent-declaration#compaction-policy-overrides) -- the full `EXECUTION.compaction` property reference. +- [Result compaction](/agent-platform/abl-reference/tools#result-compaction) and [Store result](/agent-platform/abl-reference/tools#store-result) -- per-tool compaction and `last__result`. +- [Tuning for latency](/agent-platform/latency-and-speed) -- smaller, stable prompts as a speed lever. diff --git a/agent-platform/create-agents.mdx b/agent-platform/create-agents.mdx index a56d60c60..9929a199e 100644 --- a/agent-platform/create-agents.mdx +++ b/agent-platform/create-agents.mdx @@ -50,7 +50,9 @@ Click **Create Agent** and fill in the following details: Click **Create Agent** to open the agent editor. -{/* Commented by Shruti - Patterns listed here are different. +{/* + +SK: Patterns listed here are different. ### Pattern-aware agent creation @@ -64,6 +66,7 @@ If your project uses an orchestration pattern, Studio automatically assigns a ro | **Custom** | No roles are enforced. | A context panel in the creation dialog explains how the new agent fits into the pattern, including which coordination blocks (such as ESCALATE rules) will be pre-configured. + */} ## Use the ABL Editor diff --git a/agent-platform/faq.mdx b/agent-platform/faq.mdx index 9323d10ef..e3e332a05 100644 --- a/agent-platform/faq.mdx +++ b/agent-platform/faq.mdx @@ -15,7 +15,7 @@ import { FAQSearch } from "/snippets/FAQSearch.jsx" To sign up, use your email address or use Google or GitHub login via single sign-on (SSO). A free tier is available so you can [start building agents](/agent-platform/getting-started) immediately. -To reset a forgotton password, click **Forgot password** on the login page and enter the email address associated with your account. Follow the password reset link delivered in your inbox. If you signed up using Google or GitHub SSO, you don't have a platform password. Instead, sign in using your identity provider. +To reset a forgotten password, click **Forgot password** on the login page and enter the email address associated with your account. Follow the password reset link delivered in your inbox. If you signed up using Google or GitHub SSO, you don't have a platform password. Instead, sign in using your identity provider. ### How do I invite team members to my workspace? diff --git a/agent-platform/feedback-template.mdx b/agent-platform/feedback-template.mdx index 78f2912f5..9c7e28e1b 100644 --- a/agent-platform/feedback-template.mdx +++ b/agent-platform/feedback-template.mdx @@ -281,4 +281,4 @@ Create the API key under **Settings > API Keys** with the scopes you need. | `feedback.surveys.submit` | Submitting responses. | | `feedback.surveys.read` | Retrieving responses. | -Retrieval returns comment text to any caller that holds the read scope. Issue the read scope only to systems that are allowed to see open text. \ No newline at end of file +Retrieval returns comment text to any caller that holds the read scope. Issue the read scope only to systems that are allowed to see open text. diff --git a/agent-platform/getting-started.mdx b/agent-platform/getting-started.mdx index edf93f5c0..6368df8a8 100644 --- a/agent-platform/getting-started.mdx +++ b/agent-platform/getting-started.mdx @@ -11,16 +11,12 @@ Agent Platform is available to Kore.ai customers and partners. Sign-up is enable The platform runs in multiple regions. For the US-Central Cloud, use https://agents.kore.ai/. See the region-specific URLs below. -{/* -Agent Platform is available in multiple regions. You can sign up for free to access the platform. For our US-Central Cloud, use https://agents.kore.ai/. For all regions, see the region-specific URLs. -Sign up is currently enabled only for approved domains. To request access for your domain, contact your Kore.ai partner or [contact support](https://support.kore.ai/). - */} - ### Region-specific URLs and allowlist of IPs The platform sends requests to a fixed set of egress IP addresses. If your systems use IP restrictions, add the region-specific egress IPs below to your allowlist to permit platform traffic. - + + | Region | Region-specific URL | Egress IPs | |:---------------------|:------------------------------------------------------------|:----------------------------------------------------------------| | USA-Central | [agents.kore.ai](https://agents.kore.ai) | • 172.173.109.141
• 172.212.188.206
• 20.9.69.249
• 20.12.238.143
• 104.43.208.181
• 52.173.108.174
• 172.202.57.107
• 135.119.76.33
• 130.131.217.68 | @@ -30,12 +26,13 @@ The platform sends requests to a fixed set of egress IP addresses. If your syste | Germany | [de-agents.kore.ai](https://de-agents.kore.ai) | • 3.65.5.141 | | Germany-Prime | [de-prime-agents.kore.ai](https://de-prime-agents.kore.ai) | • 20.79.56.64 | | Japan | [jp-agents.kore.ai](https://jp-agents.kore.ai) | • 20.48.103.185 | -| Japan-Prime | [jp-prime-agents.kore.ai](https://jp-prime-agents.kore.ai) | • 18.180.133.211 | +| Japan-Prime | [jp-prime-agents.kore.ai](https://jp-prime-agents.kore.ai) | • 18.180.133.211 | | Australia | [au-agents.kore.ai](https://au-agents.kore.ai) | • 52.187.236.188 | | Singapore | [sg-agents.kore.ai](https://sg-agents.kore.ai) | • 4.194.44.63 | | United Arab Emirates | [uae-agents.kore.ai](https://uae-agents.kore.ai) | • 20.74.173.252
• 20.74.153.122 | -| Kingdom of Saudi Arabia | [ksa-agents.kore.ai](https://ksa-agents.kore.ai) | 8.228.193.152 | +| Kingdom of Saudi Arabia | [ksa-agents.kore.ai](https://ksa-agents.kore.ai) | • 8.228.193.152 | | India | [ind-agents.kore.ai](https://ind-agents.kore.ai) | • 135.235.170.165 | +
### Set up your account, workspace, and initial configuration @@ -43,10 +40,11 @@ The platform sends requests to a fixed set of egress IP addresses. If your syste 1. Sign in to the platform at https://agents.kore.ai/ and create a workspace as part of the onboarding flow. 2. Invite team members to your workspace: click the **Admin/Gear** icon at the top, click **Invite members**, enter the member's email address, select a role, and click **Send invite**. 3. Configure the LLM provider and Arch AI: + 1. Register provider credentials and configure at least one supported model. See [Configure LLM](/agent-platform/administration/ai-configuration#llm-providers). - 2. Configure the model and credentials Arch uses to generate agent specifications and drive chat-based orchestration. See [Configure Arch](/agent-platform/administration/ai-configuration#arch). + 2. Configure the model and credentials that Arch uses to generate agent specifications and drive chat-based orchestration. See [Configure Arch](/agent-platform/administration/ai-configuration#arch). -Once your account and configuration are set up, you are ready to build your first AI project. +After your account and configuration are set up, you're ready to build your first AI project. --- @@ -63,12 +61,12 @@ flowchart TD P --> D["Build with Arch using CLI"] ``` -| Approach | What it is | Best for | -|:--------------------------------------------------------|:-------------|:---------| -| [Studio](#build-with-arch-in-studio) | Describe or upload your business requirements. Arch interviews you, generates a blueprint and project artifacts, then opens the project in Studio for review. | Teams that want to accelerate development through AI-assisted authoring. | -| [MCP](/agent-platform/mcp-server) | Build and manage projects from your development environment, using supported AI assistants and tools through the Model Context Protocol (MCP). | Developers who prefer working from their IDE or AI-assisted coding tools. | -| [CLI](/agent-platform/cli) | Create, test, and manage agents and projects from the terminal, and automate validation, evaluation, and deployment in CI workflows. | Developers and teams who prefer automating build, test, and deployment pipelines. | +| Approach | What it is | Best for | +|:-------------------------------------|:-------------|:---------| +| [Studio](#build-with-arch-in-studio) | Describe or upload your business requirements. Arch interviews you, generates a blueprint and project artifacts, then opens the project in Studio for review. | Teams that want to accelerate development through AI-assisted authoring. | +| [MCP](/agent-platform/mcp-server) | Build and manage projects from your development environment, using supported AI assistants and tools through the Model Context Protocol (MCP). | Developers who prefer working from their IDE or AI-assisted coding tools. | +| [CLI](/agent-platform/cli) | Create, test, and manage agents and projects from the terminal, and automate validation, evaluation, and deployment in CI workflows. | Developers and teams who prefer automating build, test, and deployment pipelines. | ## Build with Arch in Studio @@ -90,9 +88,7 @@ Arch creates your project in three phases: Interview, Blueprint, and Build. Arch analyzes your input and asks follow-up questions until it has enough information to generate a complete project blueprint. Depending on your requirements, it may ask about your business processes, communication channels, integrations, and other implementation details. - - You can upload an SOP, design document, or requirements specification instead of describing your project from scratch. Arch uses the uploaded content to generate more accurate project requirements. - + You can upload an SOP, design document, or requirements specification instead of describing your project from scratch. Arch uses the uploaded content to generate more accurate project requirements. **Example** @@ -160,11 +156,11 @@ After Arch generates your project, it opens the project in Studio and displays t The panel includes the following sections: -| Section | Description | -|---------------------------|------------------------------------------------------------------------------------| -| **Lifecycle** | Shows the current stage of the project setup and continuous improvement lifecycle. | +| Section | Description | +|:---------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| **Lifecycle** | Shows the current stage of the project setup and continuous improvement lifecycle. | | **Build and validation details** | Displays the status of each stage, including project scaffold creation, compile repair, draft review, runtime evaluation, and promotion readiness. | -| **Recommended next step** | Highlights validation issues and recommends the next actions before continuing. | +| **Recommended next step** | Highlights validation issues and recommends the next actions before continuing. | ### Review the initial evaluation @@ -200,10 +196,10 @@ Depending on your project, you can: Learn how to customize and deploy your project: -* [Agents](/agent-platform/create-agents) – Review and customize the generated agents. -* [Workflows](/agent-platform/workflows) – Modify the generated workflows and orchestration logic. -* [Tools](/agent-platform/tools-overview) – Configure production tools and integrations. -* [Knowledge](/agent-platform/knowledge) – Configure and manage knowledge sources. -* [Evaluations](/agent-platform/evals) – Run additional evaluations to validate project quality. -* [Optimize with Arch AI](/agent-platform/optimize) – Improve your project using recommendations based on evaluation results. -* [Deployment](/agent-platform/deployment) – Deploy your project to the target environment. +* [Agents](/agent-platform/create-agents) - Review and customize the generated agents. +* [Workflows](/agent-platform/workflows) - Modify the generated workflows and orchestration logic. +* [Tools](/agent-platform/tools-overview) - Configure production tools and integrations. +* [Knowledge](/agent-platform/knowledge) - Configure and manage knowledge sources. +* [Evaluations](/agent-platform/evals) - Run additional evaluations to validate project quality. +* [Optimize with Arch AI](/agent-platform/optimize) - Improve your project using recommendations based on evaluation results. +* [Deployment](/agent-platform/deployment) - Deploy your project to the target environment. diff --git a/agent-platform/glossary.mdx b/agent-platform/glossary.mdx index f74e102b7..edbcf5714 100644 --- a/agent-platform/glossary.mdx +++ b/agent-platform/glossary.mdx @@ -217,7 +217,7 @@ The default execution mode for every agent. In reasoning mode, an agent uses LLM ### Role -{/* AG: +{/* AG: - Tenant or Workspace scope in table below? - Add row for Operator role. diff --git a/agent-platform/images/prompts-create.png b/agent-platform/images/prompts-create.png index c2c486d3d..edbfa6621 100644 Binary files a/agent-platform/images/prompts-create.png and b/agent-platform/images/prompts-create.png differ diff --git a/agent-platform/knowledge.mdx b/agent-platform/knowledge.mdx index 4d5e065dc..d68607aec 100644 --- a/agent-platform/knowledge.mdx +++ b/agent-platform/knowledge.mdx @@ -616,7 +616,7 @@ Enter a query in the Query field and configure the following settings before run - Semantic - finds conceptually relevant content based on meaning, even when the exact words don't appear in the source. - Keyword - finds exact or near-exact matches. Best for structured content where precise term matching is important. -**Top K** defines the maximum number of chunks returned per query. Set this based on how much context the agent needs to compose an accurate response. A higher value returns more context but increases token consumption when the agent processes the results. +**Top K** defines the maximum number of chunks returned per query. Set this based on how much context the agent needs to compose an accurate response. A higher value returns more context but increases token consumption when the agent processes the results. Defaults to 10, and can be set from 1 to 100 in the index's Top K setting (see [Additional settings](#additional-settings)); an explicit request from a tool call is capped at 100 regardless. {/* Removed in 1.5.0 **Resolve Mode** controls how results are resolved and ranked when multiple chunks from the same or different sources are returned. Three modes are available: @@ -654,6 +654,14 @@ Manage knowledge base configuration, view indexing details, configure citation b - General - Basic information about the knowledge base. - Index Configuration - Displays the retrieval and indexing settings used by the knowledge base. + + | Setting | Range | Default | What it does | + |---------|-------|---------|--------------| + | Top K | 1 to 100 | 10 | Chunks returned when a search call doesn't specify a count. | + | Similarity threshold | 0 to 1 | 0.2 | Minimum match score; 0 means no threshold. Raise it if weak matches are causing off-topic answers. | + | Keyword Weight (Hybrid) | 0 to 1 | 0.5 | The balance between exact-term and semantic matching for a Hybrid query. Raise it toward 0.7 for FAQ or product-code content. | + | Chunk Size / Overlap | 100 to 5,000 tokens | 1,000 / 200 | Size of indexed passages, set in the content processing pipeline's chunking stage. Larger chunks carry more context per hit but fit fewer hits in the token budget. Re-ingest after changing. | + - Citations - Controls how source references appear in search results and AI-generated responses. When enabled, response includes references to the content used to generate the answer. | Option | Description | @@ -690,3 +698,52 @@ To attach a knowledge tool using the DSL editor, follow these steps: 4. Open the agent's DSL editor by clicking **DSL** at the top of the agent page. 5. Paste the copied DSL into the **Tools** section of the agent definition. 6. Compile and save the changes. + +### How the platform searches + +Knowledge base results reach the model as the output of a tool call. They are never added directly to the model's current-turn context; the model, or the platform on the model's behalf, has to call the knowledge tool to see them. + +There are two paths into a turn: + +| Path | When it applies | What happens | +|------|------------------|--------------| +| **Automatic first search** | The agent's only business tool is a single knowledge base, the agent is not a coordinator (router or orchestrator), it does not collect `GATHER` fields with inline gather, it has no handoff or delegation tools, and the turn was not forwarded by a handoff or delegation. On by default; there is nothing to switch on. | The platform searches the customer's message before the model runs, adds the results to the conversation, and tells the model to answer only from those results. If nothing is found, the model gets a normal turn and is told to search again with a more specific query. | +| **Model-driven search** | Every other agent, and any follow-up search after an automatic first search. | The model calls `search_kb_(query)` with its own query, and the results come back as that tool's result like any other tool call. | + +The automatic first search runs outside the normal tool-call path, so a knowledge tool's `on_result` / `on_error` hooks and `MODEL_CONTEXT` only apply to searches the model makes itself. To shape what the model reads on every path, including the automatic one, use `search_instructions` and `compaction.max_search_tokens` -- see [Tool-level search settings](#tool-level-search-settings) below. + +On later turns, the history keeps a placeholder for the search call, the same as for any tool result. Search results are never kept for display beyond the turn that returned them; if the conversation needs a fact again, the model searches again. + +### Tool-level search settings + +Beyond the Studio configuration in [Configure AI](#configure-ai) and [Search and test](#search-and-test), the generated `search_kb_` tool itself takes a few settings. Set them on the project tool definition -- a tool library file, or the Studio tool editor. An agent's own `TOOLS:` entry for the same tool can add only `search_instructions` and a `compaction:` block. + +```yaml +TOOLS: + search_kb_hr_policies(query: string) -> object + description: "Search the HR policy handbook. Use for leave, benefits and conduct questions." + type: searchai + kb_name: "HR Policies" + retrieval_profile: object-aware + compaction: + max_search_tokens: 6000 + search_instructions: | + Prefer the current policy year. + Always filter by the employee's country when it is known. +``` + +| Setting | Values | Default | What it does | +|---------|--------|---------|---------------| +| `search_instructions` | free text | none | Added to the tool description, and turns on query planning for the automatic first search. An agent-file value is used only when the project tool has none of its own. | +| `retrieval_profile` | `object-aware` | standard retrieval | Splits a question into up to 10 document categories, searches each in parallel with reranking, and merges the results. Useful for a knowledge base that mixes document types where one question needs several of them. | +| `compaction.max_search_tokens` | 1 to 40,000 | none when 10 or fewer chunks return; 40,000 above that | Token budget for the results the model reads. Whole chunks are dropped from the end, never cut mid-text. Lower it for voice agents and short answers -- a large budget slows the reply and dilutes grounding. | +| `queryType`, `topK`, `filters`, `similarityThreshold` (optional parameters) | `queryType`: `vector`, `hybrid`, `structured`, `semantic`, `aggregation`; `topK` up to 100 | not exposed; the tool takes only `query` | Declare these as optional parameters to let the model choose the search mode, result count, or filters on each call. Use only when the model must steer the search itself -- otherwise leave it to the planner. | + +Other tool-result [compaction](/agent-platform/abl-reference/tools#result-compaction) settings don't apply to knowledge base results -- `max_search_tokens` is the lever to use. The only other limit is the shared budget when several tools run in parallel in the same turn (100,000 characters divided across them). + +Silent traps: + +- `retrieval_profile` accepts only the exact value `object-aware`. Any other value, including different casing, is ignored. +- An agent-file `search_instructions` is ignored once the project tool already has instructions of its own. +- If citations are turned off on any one knowledge base attached to an agent, they are turned off for all of that agent's knowledge bases. +- Test retrieval with a real customer identity where possible. Studio test chats search with public permissions, so permission-restricted content may not show up there. diff --git a/agent-platform/latency-and-speed.mdx b/agent-platform/latency-and-speed.mdx new file mode 100644 index 000000000..639c3731d --- /dev/null +++ b/agent-platform/latency-and-speed.mdx @@ -0,0 +1,205 @@ +--- +title: Tuning for latency +sidebarTitle: Latency and speed +--- + +A turn's time is roughly the number of sequential model calls multiplied by the time each one takes, plus tool time, plus whatever checks run before and after. The time for each call grows with prompt size and with the model tier it uses. The three biggest wins are fewer sequential model calls per turn, smaller and more stable prompts, and fast tools that return only what the model needs. This page works through all three, plus the checks and voice settings that add their own latency. + +This page is about response latency. For Arch AI's reinforcement-learning optimization loop, see [Optimize](/agent-platform/optimize) -- a different feature with a different goal. + +## Where a turn's time goes + +| Step | Runs when | Typical cost | Lever | +|------|-----------|---------------|-------| +| Input checks | Every turn with input guardrails, before the model | 100 ms per rule; up to 5 s for a provider, 15 s for a model judge | Prefer `check` rules, and use `llm_check` only where meaning matters | +| Routing call | Every turn that starts at a router or orchestrator | One full model call | Deterministic `WHEN` on handoffs; a faster tier for coordination | +| Main model calls | 1, plus 1 per tool round | Prompt size × model tier | Fewer tool rounds; smaller prompts; fast or balanced tiers | +| Tool calls | Each round | Your API's latency (30 s default timeout) | Fast APIs, parallel calls, `MODEL_CONTEXT` | +| Tool-result summaries | A result over 10,000 characters, under `summarize` | An extra call of up to 5 s on the balanced tier | `MODEL_CONTEXT` or `structured`; a fast summarization model | +| Knowledge-base planning | KBs with `search_instructions` or filters | An extra small call (up to 5 s) | Keep instructions only where needed | +| Extraction | `GATHER` fields outside inline gather | An extra small call per turn | `EXECUTION.inline_gather: true` | +| Output checks | Every reply with output guardrails | The reply is held until checks pass; a judge adds a call | Fewer output judges; a stream-safety mode that streams | +| Reask | An output rule with `reask` fires | A full extra model call | Use `block` with a good message on latency-critical agents | +| Handoff hops | Each handoff | The receiving agent's full turn | Flatter topologies; let orchestrators answer simple asks | + +## Fewer model calls per turn + +### Topology + +- **Keep routing shallow.** Each hop -- router to specialist to sub-specialist -- adds at least one full model call. Two levels is usually enough. +- **Route deterministically where you can.** A handoff `WHEN` the runtime can evaluate against stored state -- a flag your tools or flow have already set -- fires without asking the model. `ESCALATE` triggers written as expressions work the same way. +- **Let coordinators answer simple turns.** `role: orchestrator` can answer greetings and trivial questions directly; `role: router` always spends a call routing. +- **Delegate only for real sub-tasks.** A delegate runs its own full turn while the parent waits, up to 30 seconds by default. Use a tool instead when a single API call would do. +- **Hand back only when it pays off.** `ON_RETURN: action: resume_intent` makes the parent handle a message again straight away. Use it only where the customer would otherwise have to repeat themselves. +- **Send each receiver less.** A handoff with `history: summary_only` or `last_n`, and a short summary, gives the receiver a smaller first prompt. + +### Inside an agent + +- **Answer straight from a tool.** `on_result: do: - RESPOND: "…"` sends the reply and ends the tool loop, saving the model call that would otherwise phrase it. Add a response `MODEL_CONTEXT` so later turns know what was said. +- **Use `FLOW` steps with `REASONING: false`** for fixed steps such as collecting details, calling a tool, or confirming. They run without a model call. +- **Make one tool do one job end to end.** Three sequential lookups cost three model rounds; one tool that does all three costs one. The model can also call independent tools in parallel in a single round. +- **Turn on `EXECUTION.inline_gather: true`** so field extraction happens in the same call as the reply. On a single-KB agent with `GATHER` fields, this also turns off the automatic knowledge-base search -- measure both before committing. +- **Validate inputs before calling.** `process: before: require:` rejects bad inputs without a failing API call and a retry round. +- **Use `confirm` only on irreversible actions.** Each confirmation costs a full extra turn with the customer. +- **Multi-intent completion.** With the default `completion_signal: delivered_response`, a small check runs after each queued request's reply. `task_signal` lets the agent signal completion itself instead. + +```yaml +AGENT: Order_Status +GOAL: "Tell customers where their order is" +BEHAVIOR: + role: assistant +EXECUTION: + inline_gather: true +GATHER: + order_id: + prompt: "The order number, for example A-1031" + type: string + required: true +TOOLS: + get_order_status(order_id: string) -> {status: string, eta: string, carrier: string} + description: "Current status and delivery estimate for one order" + effect: read_only + MODEL_CONTEXT: + FIELDS: [status, eta, carrier] + on_result: + do: + - RESPOND: "Order {{order_id}} is {{result.status}} with {{result.carrier}}, arriving {{result.eta}}." + MODEL_CONTEXT: "Told the customer order {{order_id}} is {{result.status}}, ETA {{result.eta}}." +``` + +This agent answers a status question in one model call (extraction plus the tool call) and one API call -- no second call is needed to phrase the answer. + +## Smaller, stable prompts and payloads + +Prompt size drives time to first token on every call in the turn, and that cost is paid again on each tool round. A prompt that starts the same way every turn also lets providers that cache automatically reuse that start. + +### Prompt and context + +- **Explicit visibility.** Declare `BEHAVIOR: role:` so `## Current Context` holds only declared and granted values. Avoid `{{context}}` in production prompts. +- **Small memory.** Session memory is sent in full on every call. Store IDs and short strings, not objects or lists. +- **Tight context budgets.** On latency-sensitive agents, lower `prompt_context.total_max_chars` (16,000 is the voice default) and `auto_tool_result_value_max_chars` (2,000 on voice) -- see [Context size, compaction, and budgets](/agent-platform/context-compaction). +- **Short history.** Keep `prior_turns: compact`, put a response `MODEL_CONTEXT` on every rich reply, and use `history: last_n` on handoffs in long conversations. +- **Short instructions.** `GOAL`, `PERSONA`, `LIMITATIONS`, and `search_instructions` are sent on every call. Move rarely needed guidance into a tool description or a `RECALL INSTRUCTION` that loads only when relevant. +- **A stable start to the prompt.** Identity, rules, and the tool list come first; values that change each turn come later, in memory and `## Current Context`. A `{{variable}}` in `GOAL` or `PERSONA` changes the very start of the prompt every time its value changes. For values that change each turn, an explicit-mode agent that declares them in memory keeps them in the memory sections and `## Current Context` instead, leaving the stable start untouched. + +### Tools + +- **Fewer tools per agent.** Every tool's description and schema is sent on every call, and the model chooses faster and better from a short list. Split large tool sets across specialists. +- **Short descriptions and parameters.** One or two sentences per tool. Hide parameters the model doesn't fill with `default_source: runtime` and `visibility_model: false`. +- **Small results.** `MODEL_CONTEXT: FIELDS` on every tool that returns more than a few fields. That avoids the summarization call and keeps each tool round small. Better still, return compact payloads from the API itself: filter, paginate, and drop fields the agent never uses. +- **Structured, not summarized.** On chat agents where speed matters, prefer `tool_results.strategy: structured` with flat `essential_fields`; summarizing costs an extra call. Voice never summarizes. +- **Tight timeouts.** Set `timeout` on the Project Tool to what the API really needs, rather than the 30-second default. Use transport retry only on idempotent reads. + +### Knowledge base + +- **Token budget.** Set `max_search_tokens` on every KB tool (2,000-4,000 for voice, more for long-form chat). +- **Fewer, better chunks.** Lower Top K and raise Similarity threshold so fewer, better chunks come back. +- **Automatic-search eligibility.** A single-KB agent gets the automatic first search, which saves a model round. Adding other business tools, handoff or delegation tools, or `GATHER` fields collected with inline gather gives that up -- see [How the platform searches](/agent-platform/knowledge#how-the-platform-searches). +- **Selective extras.** Use `search_instructions` and `retrieval_profile: object-aware` only where they improve answers. Each adds planning time or extra parallel searches with reranking. + +```yaml +AGENT: Policy_Answers +GOAL: "Answer HR policy questions from the handbook" +BEHAVIOR: + role: assistant +EXECUTION: + compaction: + tool_results: + strategy: structured + keep_recent: 1 + prior_turns: + strategy: compact + assistant_preview_chars: 160 + prompt_context: + total_max_chars: 12000 + auto_tool_result_value_max_chars: 2000 +TOOLS: + search_kb_hr_policies(query: string) -> object + compaction: + max_search_tokens: 3000 +``` + +## Checks, side calls, models, and voice + +### Guardrails and checks + +- **Order rules by cost.** Put `check` (CEL) rules first. Use provider rules for moderation and `llm_check` only for meaning patterns can't catch -- each judge is an extra model call at its checkpoint. +- **Streaming and output rules.** An agent with output guardrails or response constraints holds a streamed reply until the checks pass, in every stream-safety mode except Terminate forward and Retract capable. Nothing is shown until the full reply has been generated and checked. If both output rules and fast streaming are needed, set the project's stream-safety mode to Terminate forward: text then flows and is stopped on a violation. +- **Reask costs a full regeneration.** On latency-critical agents, prefer `block` with a good message instead. +- **Timeouts.** Lower the policy's Model and LLM timeouts for voice, and pick the fail mode deliberately. +- **PII.** Model-based detection waits up to its time budget (200 ms by default) on each scan. A pattern-only rule skips that wait, if pattern detectors cover the data. + +### Model tiers + +| Operation | Default tier | Speed lever | +|-----------|---------------|-------------| +| Coordination and routing | Most capable | Routing is a classification task -- test a balanced or fast model for routers. | +| Agent replies | Balanced | Keep balanced for quality-sensitive agents; fast for FAQ and status agents. | +| Extraction, validation, tool selection, guardrail judges | Fast | Already fast. | +| Tool-result summarization | Balanced | Set to fast, or avoid summaries entirely with `MODEL_CONTEXT`. | + +Turn off extended reasoning and thinking for conversational agents unless their answers genuinely need it. The voice low-latency profile does this by default. + +### Voice + +- **Keep the low-latency profile on.** It sets fast tiers, reasoning off, inline gather, and tight compaction. Make sure the workspace has a fast-tier model configured. +- **Fillers hide waiting; they don't remove it.** `voiceDelayMs` (300 ms in the profile) and status tags (`piggybackEnabled`, at no extra model cost) keep the caller informed while tools run. +- **Short spoken replies.** Use `CONVERSATION: speaking: max_sentences` and short instructions. +- **Realtime voice.** On Gemini Live, a long tool call blocks the voice model unless the channel's pending-tool fillers are on; Amazon Nova Sonic has its own pending-tool filler setting. Keep tool results small for realtime voice with `compaction: provider_fields`. +- **Buffered stream safety on voice.** Buffered or Gated delays the first audio until checks finish. + +## Measuring before and after + +- **Operate → Sessions → a session → Performance → LLM & Tools** lists every model and tool call in a turn with its latency, tokens, and cost. Count the sequential model calls. +- **The Traces tab → an LLM step → Summary** shows input tokens. Compare turn 1 with turn 20 to see growth. +- **Insights → Analytics Explorer → Generations** shows time to first token and latency across sessions. +- Change one thing at a time -- topology, tool payloads, tiers -- and re-run the same test conversation in a new session. + +## Speed checklist + +- [ ] At most two routing hops, with deterministic `WHEN` where state allows it. +- [ ] Status-style answers come straight from the tool (`on_result: do: RESPOND`). +- [ ] Every tool with more than a few fields has `MODEL_CONTEXT`; no tool-result summaries on hot paths. +- [ ] Fewer than about 10 tools per agent, with one- or two-sentence descriptions. +- [ ] `max_search_tokens` set on every knowledge base. +- [ ] Session memory holds IDs and short strings only. +- [ ] Routing and summarization use the cheapest tier that passes your evaluations. +- [ ] Output rules use `check` or providers, or the stream-safety mode keeps the reply streaming. + +## Design guidance + +The most reliable agents keep the prompt small and explicit: declare only what the model needs, shape every tool result, and pass state between agents on purpose rather than relying on history. + +- **Make visibility explicit.** Production agents should declare `BEHAVIOR: role:` so `## Current Context` holds only declared and granted values. Allow-list mode with `{{context}}` admits everything in the session. +- **Shape tool results at the source.** Give every tool that returns more than a few fields a `MODEL_CONTEXT`. Save anything needed on later turns to session values with `on_result`, because history keeps only a placeholder. +- **Keep memory lean.** Session memory is shown in full on every turn and is not size-limited. Hold large objects in tool results or persistent memory, not in declared session memory. +- **Hand off on purpose.** Prefer `pass` plus a templated summary, with `history: last_n` or `summary_only`, over the full default for long conversations. Give delegates everything they need in `INPUT` and `PURPOSE`. +- **Give the agent the date.** The system prompt has no current date or time -- only `GATHER` date fields get today's date, during extraction -- so supply one explicitly when an agent reasons about relative dates. +- **Keep secrets out of prompt text.** Credentials go in auth profiles, personal fields are marked `SENSITIVE`, and card data uses `SECURE_INPUT`. +- **Put stable text first.** `GOAL`, `PERSONA`, `LIMITATIONS`, and the tool list form the stable start of the prompt; values that change each turn come later, in `## Current Context`. Keeping the stable part stable helps provider-side prompt caching, which shows as Cache Read tokens on the session Overview. +- **Write guardrails for one message at a time.** A check never sees the conversation history. Choose the fail mode deliberately. + +## Pre-ship checklist + +- [ ] Each agent declares `BEHAVIOR: role:`, or its `## Current Context` has been checked in a trace. +- [ ] No `{{placeholder}}` shows unfilled in the system prompt of a test trace. +- [ ] No `{{config.*}}` or `{{env.*}}` appears in `GOAL`, `PERSONA`, `LIMITATIONS`, `SYSTEM_PROMPT`, or `RESPOND`. +- [ ] Every tool with a large or nested result has `MODEL_CONTEXT`, tested against a real response. +- [ ] Rich responses carry a response `MODEL_CONTEXT`. +- [ ] Handoff `CONTEXT:` keys are lowercase, and `history` uses a supported form. +- [ ] Delegates receive everything they need through `INPUT` or `PURPOSE`. +- [ ] Sensitive `GATHER` fields are marked `SENSITIVE` with a `PII_TYPE`. +- [ ] Guardrail rules set `kind` and `action`, use `abl.`-prefixed functions, and the policy fail mode is chosen on purpose. +- [ ] Memory is tested with an identified user; knowledge-base retrieval is tested with a real customer identity. +- [ ] Voice agents: the fast model tier has a model assigned, and custom-prompt voice agents state their own spoken-style rules. +- [ ] A long test conversation (20+ turns) has been checked for prompt size in the trace. +- [ ] Final tests ran in a new conversation, on the version that will be deployed. + +--- + +{{related}} + +- [Context size, compaction, and budgets](/agent-platform/context-compaction) -- the size budgets referenced throughout this page. +- [How a turn is built](/agent-platform/context-and-prompts) -- visibility modes and what reaches the model each turn. +- [Test agents](/agent-platform/testing) -- running and reading a test conversation. +- [Sessions](/agent-platform/sessions) -- reading a trace's Performance and Traces tabs. diff --git a/agent-platform/memory-and-state.mdx b/agent-platform/memory-and-state.mdx index 63c9a0620..723b5bb52 100644 --- a/agent-platform/memory-and-state.mdx +++ b/agent-platform/memory-and-state.mdx @@ -7,6 +7,8 @@ Agents on the platform use two kinds of memory: session memory and persistent me Learn how to declare, access, and manage session variables, persistent memory, and set up auto-recall using the ABL Editor. +Memory is distinct from **conversation history**, the turn-by-turn record of customer messages, agent replies and tool calls that an agent accumulates automatically within a session and that reaches the model on every turn without being declared. Memory, covered on this page, is the explicit state you put in `MEMORY:` -- a `SESSION:` variable, or a value made to persist with `remember:` and loaded back with `recall:`. To see what conversation history actually looked like in a given model call, open that call's Request view -- see [LLM step request and response](/agent-platform/sessions#llm-step-request-and-response). How much history a handoff or delegation carries over to the next agent is controlled separately, by `history:` on the `HANDOFF` -- see [History strategies](/agent-platform/abl-reference/multi-agent-and-supervisor#history-strategies). + ## Key concepts | Concept | Description | diff --git a/agent-platform/projects.mdx b/agent-platform/projects.mdx index d73874922..7eecf39a5 100644 --- a/agent-platform/projects.mdx +++ b/agent-platform/projects.mdx @@ -84,7 +84,7 @@ Use this method when you want the AI Architect to scaffold agents, tools, and pr 7. In the **Review** phase, confirm that the configuration is correct. 8. Click **Create**. Studio provisions the project and opens its workspace. -The richer the context you provide during the interview and upload phases, the more accurate the generated agents will be. Upload real documentation rather than summaries where possible. +The richer the context you provide during the interview and upload phases, the more accurate the generated agents are. Upload real documentation rather than summaries where possible. ### Method 2: Blank project @@ -359,14 +359,24 @@ When several workspace models share the same provider and model ID as an archive 6. In the import preview, review the [model mapping](#review-model-mapping). Where the preview asks you to choose between models, select the one to link. 7. Select **Import** to start the import. 8. Review any validation errors or conflict reports surfaced by the platform after import completes. +9. If the **Import** dialog lists unresolved workflow tool bindings, open each workflow it names and rebind the tool before you run the workflow. See [Resolve workflow tool bindings](#resolve-workflow-tool-bindings). -Imported workflows include the complete workflow definition, including nodes, edges, versions, triggers, and tool bindings. As a result, workflows are functional immediately after import and do not require manual reconfiguration. +Imported workflows include the complete workflow definition, including nodes, edges, versions, triggers, and tool bindings. Re-importing a project keeps the workflow tool bindings already in place. -## Delete a project +#### Resolve workflow tool bindings + +A workflow binds each of its tool steps to a tool in the project. When the import can't resolve a binding, for example because the archive doesn't carry the tool the workflow expects, the **Import** dialog lists the affected bindings instead of reporting success. + +Treat the list as work still to do. A workflow with an unresolved binding fails at the step that calls the missing tool, so fix every listed binding before you deploy or run the workflow. -Deleting a project removes it and all of its contents permanently. +| What to do | When | +|:-----------------------------------------------------------------------|:-------------------------------------------------------------------| +| Import or create the missing tool, then rebind the workflow step to it | The tool belongs in the project and the archive didn't include it. | +| Rebind the workflow step to an existing tool | The project already holds an equivalent tool under another name. | + +## Delete a project -**To delete a project:** +Deleting a project removes it and all of its contents permanently. To delete a project, follow these steps: 1. Open the Projects dashboard. 2. Click the three-dot menu on the card of the project you want to delete. @@ -380,11 +390,11 @@ Deleting a project removes it and all of its contents permanently. Some project features depend on workspace configuration or your assigned role. If a feature appears unavailable, check the conditions below. -| Feature | Requirement | -| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | -| **AI Architect** | An LLM provider must be configured under **Admin > Models**. Otherwise an in-panel banner is shown. | -| **Platform Admin** link | Visible only to users with super-admin permissions. | -| **Admin pages** (Members, Models, Security) | Require workspace administrator permissions. | -| **Some Insights pages** | Agent Performance, Quality Monitor, and Customer Insights may show a "coming soon" placeholder if not yet enabled for your workspace. | +| Feature | Requirement | +|:-----------------------------------|:----------------------------------------------------------------------------------------------------| +| **AI Architect** | An LLM provider must be configured under **Admin > Models**. Otherwise an in-panel banner is shown. | +| **Platform Admin** link | Visible only to users with super-admin permissions. | +| **Admin pages** (Members, Models, Security) | Require workspace administrator permissions. | +| **Some Insights pages** | Agent Performance, Quality Monitor, and Customer Insights may show a "coming soon" placeholder if not enabled for your workspace. | -If you expect access to a feature and don't have it, contact your workspace administrator. \ No newline at end of file +If you expect access to a feature and don't have it, contact your workspace administrator. diff --git a/agent-platform/prompts.mdx b/agent-platform/prompts.mdx index 66d24eaf2..677bef7e5 100644 --- a/agent-platform/prompts.mdx +++ b/agent-platform/prompts.mdx @@ -1,6 +1,6 @@ --- -title: Prompt library -sidebarTitle: Prompts +title: Prompts library +sidebarTitle: Prompts library --- It's a central place to create, manage, and reuse prompt templates across your agents and workflows — with version tracking, response testing, and reference lookup built in. diff --git a/agent-platform/safety-and-guardrails.mdx b/agent-platform/safety-and-guardrails.mdx index d12e262c0..6292af7f2 100644 --- a/agent-platform/safety-and-guardrails.mdx +++ b/agent-platform/safety-and-guardrails.mdx @@ -10,7 +10,7 @@ The platform uses three enforcement layers to control agent behavior and protect | Enforcement layer | Description | Example | |-------------------|-------------|---------| | [Guardrails](#input-guardrails) | Safety and quality checks applied to agent input and output content. | Blocking abusive language or redacting sensitive information from responses. | -| [Limitations](/agent-platform/create-agents#define-identity-and-persona) | Reasoning-based guidance enforced through the model. Defines how the agent should behave, what it should avoid, and the scope it should operate within. | Instructing an agent to avoid financial advice or remain within a support domain. | +| [Limitations](/agent-platform/create-agents#define-identity-and-persona) | Reasoning-based guidance enforced through the model. Defines how the agent behaves, what it avoid, and the scope it operates within. | Instructing an agent to avoid financial advice or remain within a support domain. | | [Constraints](/agent-platform/concepts#constraints-and-guardrails) | Runtime business-rule validations that prevent execution when required conditions aren't met. | Requiring a customer ID before allowing an order lookup or payment action. | ## Constraints vs. guardrails @@ -42,6 +42,22 @@ flowchart TD D --> |Toxicity checks\nPII redaction\nContent filtering| E[Final Response Returned to User] ``` +### Guardrail checkpoints + +A guardrail rule's `kind` sets which single item it checks. A check sees only that one item -- never the conversation history or the system prompt -- so write each rule to judge one message on its own. + +| Checkpoint | `kind` | What the check sees | When it runs | +|---|---|---|---| +| Input | `input` | The customer's message. Model-based tiers see it with PII already tokenized. | Before the model is called. | +| Output | `output` | The final reply, plus up to 20 of this turn's tool results (4,096 characters each) when built-ins are enabled. | Before the reply is delivered. | +| Tool call | `tool_input` | The tool's arguments, as JSON. | Before the tool runs. | +| Tool result | `tool_output` | The result as the model would see it. | After the tool runs, before the model reads it. | +| Handoff | `handoff` | The context being passed, and the source and target agents. | Before the context is transferred, using the source agent's rules. | + +`kind: both` is shorthand for `input` plus `output`. See [Tool and handoff guardrails](#tool-and-handoff-guardrails) below for `tool_input`, `tool_output`, and `handoff`. + +A check that reads `content`, `session_state`, or `tool_results` needs `EXECUTION: guardrail_builtins: true`. Without it, the check errors and -- under the default Open fail mode -- the message it would have checked is let through. + --- ### Guardrail configuration levels @@ -208,6 +224,46 @@ Output guardrails support: --- +## Tool and handoff guardrails + +Beyond `input`, `output`, and `both`, a rule's `kind` can target a tool call, a tool's result, or a handoff to another agent. + +Use `kind: tool_input` to check a tool's arguments before the call runs: + +```yaml +GUARDRAILS: + block_large_transfers: + kind: tool_input + check: abl.matches_pattern(tool_input.amount, "^[0-9]{6,}$") + action: block + message: "That transfer amount needs manual review." +``` + +Use `kind: tool_output` to check a tool's result before the model reads it: + +```yaml +GUARDRAILS: + scrub_tool_pii: + kind: tool_output + check: abl.contains_pii(tool_output) + action: redact +``` + +Use `kind: handoff` to check the context passed to another agent. It is evaluated with the source agent's rules before the transfer happens: + +```yaml +GUARDRAILS: + handoff_review: + kind: handoff + llm_check: "Does this handoff include unredacted financial account numbers?" + action: block + message: "This conversation needs a different routing path." +``` + +A `block` at any of these checkpoints withholds the call, result, or handoff and returns an error to the model instead of ending the conversation. Pair `escalate` with your own routing setup -- see [Agent transfer](/agent-platform/administration/agent-behavior-settings#agent-transfer) -- since a guardrail `escalate` action only sends the escalation message and doesn't transfer the conversation by itself. + +--- + ## DSL and UI mapping The platform maintains a one-to-one mapping between the UI configuration and the DSL/ABL definition. This lets you: diff --git a/agent-platform/sessions.mdx b/agent-platform/sessions.mdx index 772900875..9a8d5dd57 100644 --- a/agent-platform/sessions.mdx +++ b/agent-platform/sessions.mdx @@ -8,7 +8,9 @@ A session represents a conversation between an agent in an Artemis project and a It stores the conversation context, maintains state across interactions, and remains active until it is closed. -{/* AG: items to be documented when available or in the next round of updates +{/* + +AG: items to be documented when available or in the next round of updates - How to search sessions. How to filter and/or sort to zero-in on a few specific sessions. - To filter using phone number, see feature request ABLP-4425. @@ -21,7 +23,7 @@ A session moves through the following set of states from creation to eventual ar | Status | Meaning | |:------------|:-------------------------------------------------------| -| `active` | Session in progress; agent is currently processing. | +| `active` | Session in progress; agent is processing right now. | | `idle` | Session in progress; waiting for user input. | | `ended` | Session completed by user action, or an idle timeout fired after COMPLETE in the DSL (timeout is configurable per project per channel). | | `completed` | Agent finished by calling COMPLETE. | @@ -126,6 +128,29 @@ Each turn reports where its time went, so you can find the step that slowed a re When a lifecycle hook invokes a tool through a `CALL` action, the call appears in the trace as its own tool call, tagged with the hook type. Each one shows the URL, request, response, duration, and whether the call succeeded or failed. Use these entries to confirm that a hook ran and to see what it sent and received. +#### LLM step request and response + +Each LLM step in the timeline expands to show the exact call made to the model for that step. + +| Sub-tab | What you get | +|---------|----------------| +| Request | The full request sent to the model: `systemPrompt` (the complete system prompt text), the `messages` array (conversation history, with tool calls and results exactly as the model saw them), and `tools` (the tool list with schemas). This is the source of truth for what the model actually received -- when a reply is surprising, read this before changing the agent's ABL. | +| Response | The model's raw reply. | +| Summary | Tokens in and out, cost, and provider options for the call. | + +What to check in the Request view: + +- `systemPrompt` -- look for unfilled `{{placeholders}}`, missing memory values, and `_contextLimited` markers. +- `messages` -- check how earlier turns were compacted, whether tool results show as `**COMPACTED FOR CHAT HISTORY**`, and what a handoff or delegation passed through. +- Tool results for the current turn -- check whether a `MODEL_CONTEXT` view or the compaction strategy's output appears, and look for truncation markers. +- `tools` -- confirm each tool's description and parameters read the way you intend the model to use them. + +Secret-looking values are always masked in stored traces, and personal data appears as redacted tokens when the project's PII policy scrubs traces. Stored request payloads are capped at 256 KiB and responses at 128 KiB; use **Export entire trace** on the session page to download every event for offline review. + +#### Execution tree view + +Selecting a node in the session page's left-hand execution tree shows the same payload scoped to that one node: **Request** / **Response** for an LLM step, or **Input** / **Output** for a tool step. Use it to jump straight to one agent's call or one tool's exact input and output inside a longer trace, instead of scrolling the full timeline. + ### Errors Lists errors or warnings recorded in the session. @@ -272,8 +297,10 @@ Use call recordings to investigate issues with a voice call. - **Tell the caller yourself.** The platform doesn't play a "this call is recorded" announcement or show the caller a recording indicator. If your region requires consent or a notice, add it to your agent's opening prompt. - **Storage location.** Recordings are stored in the storage configured for your workspace. Use your own storage account if the audio must stay in a specific region. -{/* Not available yet -The session panel shows whether storage is Kore-managed or customer-managed. +{/* + +Not available yet. The session panel shows whether storage is Kore-managed or customer-managed. + */} #### Troubleshoot if recording doesn't start @@ -287,7 +314,7 @@ Check these in order - the first "no" is usually the cause. 5. Was the call started after you saved the setting? Recording only applies to new calls. 6. Did you wait about 15 minutes and click **Refresh**? -If you've verified all six checks and the recording is still unavailable, contact the support team and provide the environment details, project name, session ID, and the approximate call date and time. +If you've verified all six checks and the recording is unavailable, contact the support team and provide the environment details, project name, session ID, and the approximate call date and time. #### Turn recording off @@ -417,4 +444,4 @@ Post-agent action is **Return to bot**. The conversation session is **not** clos - Transfer metadata is written onto the session. - The status changes from `escalated` back to `active`. -- The bot resumes handling messages as usual. The session is closed later when the conversation ends through the agent, automatic timeout, or another transfer that terminates the conversation. \ No newline at end of file +- The bot resumes handling messages as usual. The session is closed later when the conversation ends through the agent, automatic timeout, or another transfer that terminates the conversation. diff --git a/agent-platform/supported-models.mdx b/agent-platform/supported-models.mdx index 0a6e401e2..d1c2c6c57 100644 --- a/agent-platform/supported-models.mdx +++ b/agent-platform/supported-models.mdx @@ -157,8 +157,8 @@ The supported models list includes the provider name, model name, and model iden ### Anthropic -| Display Name | Model ID | -|----------------------------------|-----------------------------------------------| +| Display Name | Model ID | +|---------------------------------------|----------------------------------------------| | Claude Haiku 4.5 (Microsoft Foundry) | microsoft_foundry/claude-haiku-4-5-20251001 | | Claude Opus 4.6 (Microsoft Foundry) | microsoft_foundry/claude-opus-4-6 | | Claude Opus 4.7 (Microsoft Foundry) | microsoft_foundry/claude-opus-4-7 | @@ -167,10 +167,10 @@ The supported models list includes the provider name, model name, and model iden ### OpenAI -| Display Name | Model ID | -|---------------------------|--------------------------------| -| GPT-4o (Microsoft Foundry) | microsoft_foundry/gpt-4o | -| GPT-5 (Microsoft Foundry) | microsoft_foundry/gpt-5 | +| Display Name | Model ID | +|----------------------------|--------------------------| +| GPT-4o (Microsoft Foundry) | microsoft_foundry/gpt-4o | +| GPT-5 (Microsoft Foundry) | microsoft_foundry/gpt-5 | ### Meta diff --git a/agent-platform/testing.mdx b/agent-platform/testing.mdx index 2435c7ee0..1e388b291 100644 --- a/agent-platform/testing.mdx +++ b/agent-platform/testing.mdx @@ -82,3 +82,15 @@ Session ``` For repeatable, automated testing beyond manual chat, the platform supports Personas, Scenarios, and Evals. [Learn More](/agent-platform/evals). + +## Pre-ship checklist + +Before deploying a new or updated agent, confirm the basics in a test trace: + +- [ ] No `{{placeholder}}` shows unfilled in the system prompt. +- [ ] Every tool with a large or nested result has `MODEL_CONTEXT`, tested against a real response. +- [ ] Memory is tested with an identified user; knowledge-base retrieval is tested with a real customer identity. +- [ ] A long test conversation (20+ turns) has been checked for prompt size growth. +- [ ] Final tests ran in a new conversation, on the version that will be deployed. + +See [Pre-ship checklist](/agent-platform/latency-and-speed#pre-ship-checklist) for the full list, including guardrail, handoff, and voice-specific checks. diff --git a/agent-platform/workflows.mdx b/agent-platform/workflows.mdx index 42ad93536..c935df276 100644 --- a/agent-platform/workflows.mdx +++ b/agent-platform/workflows.mdx @@ -459,6 +459,7 @@ You can export an individual workflow and import it into another project as an e 3. The workflow is downloaded as a `.workflow.json` file. The workflow export includes the workflow definition and references to dependent components, such as agents, tools, and auth profiles. These dependent components are not exported with the workflow. +Configuration variable references, including references to secret variables, are included as dependencies in the exported workflow. Configuration variable values are not exported. Hard-coded secret values in node configurations are not exported and can prevent the workflow from being exported. Workflow trigger definitions are not included in workflow exports. You must configure triggers manually after importing the workflow. @@ -468,11 +469,13 @@ The workflow export includes the workflow definition and references to dependent 2. Click **Choose file** and select the workflow export file. 3. In the Import Workflow dialog, enter a name for the workflow, and click **Preview**. 4. Review the workflow details and dependencies. Missing dependencies are identified in the preview. -5. If dependencies are missing, resolve them or select **Import with unresolved dependencies unselected** to continue without them. +5. If dependencies are missing, resolve them or select **Import with unresolved dependencies unselected** to continue without resolving them. 6. Click **Import**. The imported workflow is created as an editable draft. Unresolved dependencies must be manually relinked before you run or publish the workflow. +If a referenced configuration variable is missing from the target project, the import can still proceed. The missing configuration variable is flagged as an unresolved dependency and must be configured before you run or publish the workflow. + --- ## Execute and inspect workflows diff --git a/docs.json b/docs.json index 0a13cf143..ce784dd39 100644 --- a/docs.json +++ b/docs.json @@ -88,7 +88,9 @@ "/agent-platform/inbuilt-tools/index" ] }, + "/agent-platform/context-and-prompts", "/agent-platform/memory-and-state", + "/agent-platform/context-compaction", "/agent-platform/gather-data", "/agent-platform/prompts", "/agent-platform/feedback-template", @@ -114,6 +116,7 @@ "/agent-platform/testing", "/agent-platform/evals", "/agent-platform/optimize", + "/agent-platform/latency-and-speed", { "group": "Govern", "pages": @@ -169,6 +172,7 @@ [ "/agent-platform/abl/reference/language-overview", "/agent-platform/abl/reference/scripting-constructs", + "/agent-platform/abl/reference/configuration-reference", "/agent-platform/abl/reference/agent-declaration", "/agent-platform/abl/reference/multi-agent-and-supervisor", "/agent-platform/abl/reference/behavior-profiles", diff --git a/drafts/.remarkrc.mjs.txt b/drafts/.remarkrc.mjs.txt new file mode 100644 index 000000000..9e0bdbf69 --- /dev/null +++ b/drafts/.remarkrc.mjs.txt @@ -0,0 +1,9 @@ +import remarkPresetLintRecommended from 'remark-preset-lint-recommended'; + +export default { + plugins: [ + remarkPresetLintRecommended, // Use standard recommended rules + // You can add more granular rules here, for example: + // ['remark-lint-list-item-indent', 'space'], + ], +}; diff --git a/drafts/eslint.config.js.txt b/drafts/eslint.config.js.txt new file mode 100644 index 000000000..1e80d5cd9 --- /dev/null +++ b/drafts/eslint.config.js.txt @@ -0,0 +1,20 @@ +import mdx from 'eslint-plugin-mdx'; + +"extends": ["plugin:mdx/recommended"] + +export default [ + // Apply MDX configurations to all .mdx files + { + files: ['**/*.mdx'], + ...mdx.flat, + processor: mdx.processors.remark, + settings: { + 'mdx/remark': true, // Enforces ESLint to read and track remark-lint rules + }, + }, + // Optional: lint standard code blocks wrapped inside MDX + { + files: ['**/*.mdx'], + ...mdx.flatCodeBlocks, + } +];