---
title: Connect Agent UI (Oct 2026): Pick the Build Path by Constraint
description: As of October 27, 2026, Amazon Connect Customer offers 4 supported ways to build an agent UI. Customer Profiles bills $0.005 per imported-data profile utilized per day, and 3P apps run only in the agent workspace, not in custom desktops.
url: https://www.factualminds.com/blog/amazon-connect-custom-agent-ui-customer-profiles-2026/
datePublished: 2026-10-27T00:00:00.000Z
dateModified: 2026-10-27T00:00:00.000Z
author: palaniappan-p
category: Cloud Architecture
tags: amazon-connect, contact-center, customer-profiles, agent-workspace, amazon-connect-streams, aws
---

# Connect Agent UI (Oct 2026): Pick the Build Path by Constraint

> As of October 27, 2026, Amazon Connect Customer offers 4 supported ways to build an agent UI. Customer Profiles bills $0.005 per imported-data profile utilized per day, and 3P apps run only in the agent workspace, not in custom desktops.

As of October 27, 2026, Amazon Connect Customer gives you 4 supported ways to build an agent UI: a third-party (3P) app inside the agent workspace, a step-by-step guide built from views, a custom desktop that embeds the CCP with Amazon Connect Streams, and a CTI adapter that puts the CCP inside a CRM. They differ in who owns the softphone, the sign-in, and the accessibility surface. Customer Profiles feeds all four, and the $0.005 per imported-data profile utilized per day price is the number to carry into the budget.

Naming note: AWS now writes "Amazon Connect Customer" in many docs. The console and APIs are the same. This post uses Connect.

I have not run this against a production queue. The facts below come from AWS and open-source documentation linked inline. The code is in the [artifact folder](https://www.factualminds.com/examples/architecture-blog-2026/connect-commerce-context/agent-workspace/README.md) and has one `node --test` file that needs no AWS credentials.

Related builds in this series: [Connect + Shopify](https://www.factualminds.com/blog/amazon-connect-shopify-integration-2026/), [BigCommerce and WooCommerce](https://www.factualminds.com/blog/amazon-connect-bigcommerce-woocommerce-integration-2026/), and [NetSuite, Odoo, JD Edwards](https://www.factualminds.com/blog/amazon-connect-erp-integration-netsuite-odoo-jd-edwards-2026/). For the commerce landing page see [Amazon Connect for eCommerce](https://www.factualminds.com/services/amazon-connect/aws-retail-ecommerce/).

---

Customer Profiles in depth: object type mappings, identity resolution, calculated attributes, quotas and deletion are in the [Customer Profiles implementation guide](https://www.factualminds.com/blog/amazon-connect-customer-profiles-guide-2026/). Here the focus is how profile context reaches the agent's screen.

## The four options, labeled

| Option | Label | Who owns the UI | Fits when | Watch for |
| --- | --- | --- | --- | --- |
| **Agent workspace + 3P app** | Native host, your code in an iframe | AWS owns CCP, Profiles, Cases. You own one app. | You need an order or account panel next to native tools | App must allow framing from the workspace. 3P apps are not supported in custom agent applications |
| **Step-by-step guide (views)** | Native | AWS hosts the view. You write flow and JSON. | A scripted procedure with branching and data from a Lambda | A guide run creates its own chat contact. Billed per message |
| **Custom desktop (Streams)** | Native library, custom engineering | You own the page, SSO, focus, errors | Agents must work inside a product you already operate | Origin allowlist, softphone and sign-in handling, upgrades |
| **CRM CTI adapter** | Supported integration | The CRM vendor's UI hosts the CCP | The CRM is the system of record for agents | Two allowlisted origins. Verify adapter scope in vendor docs |

Pick by the constraint that is hardest to change. If agents already live in Salesforce, do not build a desktop. If the only gap is one panel, do not build a desktop either.

---

## Option 1: the agent workspace with 3P apps

The [agent workspace](https://docs.aws.amazon.com/connect/latest/adminguide/3p-apps.html) already includes Customer Profiles, Cases, agent assist, and step-by-step guides. A 3P app is a web app that Connect renders in an iframe, opened from the Apps launcher. AWS documents three integration types: Standard application, Service (headless, runs for the whole session and reacts to events such as connect, disconnect, and after contact work), and MCP server (tools for Connect AI agents through a Bedrock AgentCore gateway).

Setup facts from the admin guide:

- The access URL must start with `https`, unless it is localhost.
- The page must be frameable. The `Content-Security-Policy frame-ancestors` directive should be `https://your-instance.my.connect.aws`. A value of `same origin` or `deny` blocks it.
- You set a contact scope (refresh per contact or per browser session) and an initialization timeout in milliseconds.
- Integrations need an instance that uses a service-linked role, and you assign the app to security profiles.
- 3P apps are available in 10 Regions per the release notes, among them US East (N. Virginia), US West (Oregon), Canada (Central), Frankfurt, London, Singapore, Sydney, Tokyo, Seoul, and Cape Town. The Integrations menu is missing in other Regions.
- SSO federation is supported. Your app can complete sign-in in the iframe only if your identity provider allows its sign-in page to be framed.

### The SDK

The [Connect SDK](https://docs.aws.amazon.com/agentworkspace/latest/devguide/getting-started-install-sdk.html) ships as npm packages. `@amazon-connect/app` is the minimum for every app. AWS lists `@amazon-connect/core`, `@amazon-connect/contact` (ContactClient), `@amazon-connect/voice`, `@amazon-connect/email`, and `@amazon-connect/app-manager` (hosts Cases and step-by-step guides) among the packages. You initialize `AmazonConnectApp` first, which returns `{ provider }`, then create clients.

Permissions are explicit. An app that subscribes to an event or makes a request it was not granted fails. The SDK's `AppConfig.permissions` lists what the app received, which is the first check when a handler never fires.

3P apps are supported only in the agent workspace, and a custom Streams desktop cannot host them. That decides many designs.

---

## Option 2: step-by-step guides (views)

A guide is a flow with a Show view block. [Views](https://docs.aws.amazon.com/connect/latest/adminguide/view-resources-sg.html) have a template, an input schema, and actions, and you can reference any flow namespace, including `$.External`, so a view can show Lambda data. Use the Set JSON option for mapping. The Flows > Views tab renders a view next to its JSON, which AWS's own best-practices post recommends for avoiding JSON typos.

Two facts shape the design. A running guide creates a separate chat contact with its own record, invisible to the user. And the pricing appendix lists step-by-step guides at $0.010 per message (Oct 27, 2026), so a long guide adds up.

Views can also be embedded in a Streams page with `connect.agentApp.initApp("customviews", ...)`. The Streams docs warn that skipping lifecycle cleanup leaves the view counting against chat concurrency until the contact duration (default 24 hours) or the Show view timeout ends. Call `terminateCustomView()` when you close the iframe.

---

## Option 3: a custom desktop with Streams

[`amazon-connect-streams`](https://github.com/amazon-connect/amazon-connect-streams) embeds the CCP in an iframe through `connect.core.initCCP(container, { ccpUrl, ... })` and exposes events. About the `connectRTC` name: the softphone WebRTC library is the separate [`connect-rtc-js`](https://github.com/aws/connect-rtc-js) repository, and the Streams docs tell you to upgrade it together with Streams.

Facts that bite in real builds, all from the Streams README:

- Approved origins: every page that initializes Streams must be on an origin you add under Approved origins on the instance. Entries must be HTTPS and include scheme, host, and port.
- One browser: using several browsers at once for the same instance is not supported and breaks RTC. Tabs on one browser stay synchronized.
- SAML: use the `loginUrl` option to start sign-in through your identity provider. `loginPopup` defaults to `true`.
- Framed softphone: `allowFramedSoftphone` defaults to `false`. If your own page is framed, media will not work until you set it deliberately.
- Storage access settings in `initCCP` were deprecated in November 2024.
- Chat and tasks need `amazon-connect-chatjs` and `amazon-connect-taskjs`, imported after Streams.
- Plan a CCP version path. AWS maintains a migration guide for the new CCP at `/ccp-v2`.

A media-less CCP, which does not open the media ports, is possible with Streams, but the AWS networking docs say it still needs CloudFront access.

### Contact events and attributes

Context line: Streams 2.x events as documented in `Documentation.md`. This is the shape used in `app.mjs` in the artifact. It reads a flow attribute and never blocks the accept button.

```js
connect.contact((contact) => {
  contact.onConnecting(() => loadContext(contact)); // attrs are { name, value } objects
  contact.onConnected(() => focusProfileHeading());
  contact.onEnded(() => clearContextAndRestoreFocus());
});
connect.agent((agent) => {
  agent.onSoftphoneError((e) => say(`Audio problem: ${e.errorType}`)); // errorType, errorMessage, endPointUrl
  agent.onWebSocketConnectionLost(() => say('State may be out of date'));
});
```

`contact.getAttributes()` returns a map where each value is `{ name, value }`, and it returns `null` when the user is only monitoring the contact. Handle both.

---

## Option 4: CRM-embedded CTI

For Salesforce, AWS documents the [Connect CTI Adapter](https://docs.aws.amazon.com/connect/latest/adminguide/salesforce-integration.html): a managed Salesforce package plus an AWS serverless application, with a WebRTC CCP inside Salesforce. It uses the Streams API and Salesforce Open CTI. You must allowlist both the Salesforce page origin and the adapter's Visualforce origin, or the CCP will not open. Install in a sandbox first, as AWS recommends. This is a supported integration (AWS and Salesforce provided). Our [Salesforce on AWS integration page](https://www.factualminds.com/integrations/salesforce-aws/) covers the wider picture.

I did not verify ServiceNow or Zendesk CTI adapters in this pass. Both are covered below as Customer Profiles data sources, which is a different thing. Check the vendor's marketplace listing and the Connect admin guide before you assume an adapter exists for your CRM.

---

## Customer Profiles, the data layer under every option

### Domains, profiles, and object types

A [domain](https://docs.aws.amazon.com/connect/latest/adminguide/customer-profiles-terminology.html) is the top-level container: profiles, object types, keys, encryption, and retention. A profile has one standard profile object (fields such as `FirstName`, `LastName`, `PhoneNumber`, `EmailAddress`, `ShippingAddress`, and custom `Attributes`) and any number of profile objects, each up to 250 KB of JSON. Other standard objects exist for assets, orders, and cases.

An object type mapping turns source records into this model. AWS's five questions are worth copying: what makes a record unique (exactly one `UNIQUE` key), what ties it to a person (at least one `PROFILE` key), which values go on the profile (field `Target` such as `_profile.FirstName`), whether it also describes an order or case, and what else should be searchable. Re-sending a record with the same `UNIQUE` value replaces it. Every stored key is also searchable.

### What can feed it

| Source | Label | Notes |
| --- | --- | --- |
| Salesforce, ServiceNow, Zendesk, Marketo | Supported integration | Pre-built, through Amazon AppFlow. Periodic sync |
| Amazon S3 | Native source | You define the template and mapping |
| Segment, Shopify | Supported integration | AWS describes near real-time ingestion |
| Your own code | Custom engineering | `PutProfileObject` API |
| NetSuite, Odoo, JD Edwards, BigCommerce, WooCommerce | Not a documented pre-built connector | Use S3 or `PutProfileObject`. See the sibling posts |

You need a customer managed KMS key before integrating, and AppFlow needs `appflow:CreateFlow` and `DeleteFlow`. The Shopify keys `_shopifyCustomerId` and `_shopifyOrderId` are valid `SearchProfiles` key names. The S3 and AppFlow paths are not instant: do not promise agents that an order placed seconds ago is on the profile.

### Identity resolution

[Rule-based identity resolution](https://docs.aws.amazon.com/connect/latest/adminguide/how-rule-based-identity-resolution-works.html) matches profiles by up to 15 attributes per rule, in levels. Follow the AWS tips: include a high-cardinality attribute such as phone, email, or account number. A rule level made only of attributes shared by more than 500 profiles is skipped. Enable Match only first, read the results, and only then set `MaxAllowedRuleLevelForMerging`.

### Calculated attributes

[Calculated attributes](https://docs.aws.amazon.com/connect/latest/adminguide/customerprofiles-calculated-attributes-apis.html) aggregate profile-object data: AVERAGE, COUNT, SUM, FIRST_OCCURRENCE, LAST_OCCURRENCE, MINIMUM, MAXIMUM, MAX_OCCURRENCE, RECENT_OCCURRENCES. Each references one object type and at most two fields. `UseHistoricalData` backfills older records. The default `_frequent_caller` counts contacts in a time window. `ListCalculatedAttributesForProfile` triggers the calculation and returns `Value` and `IsDataPartial`, so show partial data as partial.

### Profiles APIs and the agent view

`SearchProfiles` takes a required `KeyName` and `Values`, up to 4 `AdditionalSearchKeys`, a `LogicalOperator` (default `OR`), and `MaxResults` (default 20). Predefined key names include `_account`, `_email`, `_phone`, `_fullName`, `_orderId`, and `_ctrContactId`. Note the default: an `OR` search across two keys can return two people. Set `AND` or handle the ambiguous case, as the sample does.

In the workspace, agents see the profile of the contact in focus. In a flow, the Customer profiles block looks up details for routing and greetings. In a custom desktop, `connect.agentApp.initApp("customerprofiles", ...)` embeds the native profile app at `/customerprofiles-v2/`. That is often better than rebuilding the profile view.

Security profile permissions control agent access: `CustomerProfiles.View`, `.Edit`, `.Create`, plus separate calculated-attribute, segment, and explorer permissions. Give agents View, not Create, unless the job needs it.

### Pulling CRM and ERP context

Do not copy the whole CRM into profiles. Put the identifiers and a few agent-facing facts in Profiles, and fetch live order or invoice detail from the system of record on demand. For the commerce side see [Connect + Shopify](https://www.factualminds.com/blog/amazon-connect-shopify-integration-2026/). For ERP, the call patterns are in [the NetSuite, Odoo, JD Edwards post](https://www.factualminds.com/blog/amazon-connect-erp-integration-netsuite-odoo-jd-edwards-2026/), and a flow-side Lambda must return a flat string map within 8 seconds (see below).

---

## API integration from the custom UI

Never put AWS credentials in a browser. The browser calls your backend. The backend holds a role limited to one domain and returns the minimum fields. The artifact's `profile-context.mjs` takes the Customer Profiles call as an injected function, validates input, caps the wait, and returns a flat string map with the email masked.

Context line: Node 24 ESM handler from the artifact, with a mock client as in the test. In Lambda, replace the mock with `SearchProfilesCommand` from `@aws-sdk/client-customer-profiles`.

```js
import { makeHandler } from './profile-context.mjs';
const handler = makeHandler(
  (p, opts) => client.send(new SearchProfilesCommand(p), opts), // injected: tests pass a fake; opts.abortSignal cancels on timeout
  { domainName: 'my-domain', timeoutMs: 3000 }
);
const { statusCode, body } = await handler({ phone: '+14155550123' });
// 200 body: { found, profileId, displayName, accountNumber, emailMasked } or { found:'false', reason: 'no_match' | 'ambiguous' }
// 504 on timeout, 502 on AWS errors (reason: auth, throttled, misconfigured or upstream_error)
```

Least privilege: one role for this backend, allowed `profile:SearchProfiles` on the domain ARN and nothing else (confirm action names in the Service Authorization Reference). The handler logs one line per failure with the reason and the AWS error name, never the phone or email. Failures return 502 or 504 rather than 200, so API Gateway and browser monitoring see them. If the same lookup runs inside a flow Lambda instead, AWS caps synchronous invocation at 8 seconds, retries on error up to three times until the timeout, and with response validation set to `STRING_MAP` the function must return a flat object of string values. Use `JSON` validation only if you need nested data.

---

## Accessibility

AWS's agent workspace guide recommends meeting WCAG 2.1 AA for your own app and names axe, Pa11y, Lighthouse, WAVE, plus NVDA, JAWS, or VoiceOver and keyboard-only passes. It also points to AWS Artifact for the Connect UI's accessibility compliance reports. Those reports cover AWS's UI, not your page.

What the stub does, and why:

- A `role="status"` live region announces incoming, connected, and ended. No focus change on `onConnecting`, so a ringing call does not yank focus out of the CCP.
- The connected announcement says whether context is ready, still loading or unavailable, and a failed lookup announces its reason (session or permissions, timeout, more than one profile). It never claims context is ready when it is not.
- Each lookup is tied to its contact ID. A slow answer that arrives after the contact ended is dropped, so it can never paint the previous caller's name onto the next contact.
- Focus moves to the profile heading only on `onConnected`, after the agent chose to accept. On `onEnded`, focus returns to where it was.
- Profile text uses `textContent`, never `innerHTML`.
- The CCP container has a labeled `region`. The CCP interior is an iframe you cannot restyle.

This stub has not been through a screen reader pass. Treat it as a starting point for your own NVDA and keyboard testing.

---

## What broke

**Counter-case, modeled and not a cited client.** A phone number is shared by two people in one household, both imported from a CRM. The lookup is `_phone` with the default `OR`. `SearchProfiles` returns two items. A UI that takes `Items[0]` shows the wrong person's order history, and the agent reads it aloud. Detection: a compare of the displayed profile ID to the one the agent confirms verbally. Fix: ask for two items, treat more than one as ambiguous, show "verify the customer," and tighten matching rules while in Match only mode. The test `no match and ambiguous match both return found=false` locks that behavior.

A second failure is operational. The Streams page loads but `onAuthFail` fires after the sign-in expires and nobody sees it, because the status text was visual only. The stub routes it to the live region and tells the agent to sign in from the CCP.

---

## Errors, state, and testing

- Init failures: the CCP shows "Initialization Failed" when required domains or ports are not allowlisted. AWS's fix is the domain allowlist and the endpoint test utility, not code.
- Softphone: `agent.onSoftphoneError` gives `errorType`, `errorMessage`, `endPointUrl`. Show a message. Do not retry in a loop.
- State reconciliation: treat `agent.getState()` as truth after `onWebSocketConnectionLost` and `onWebSocketConnectionGained`. Do not keep a shadow copy that survives a reconnect.
- Local: run `node --test` on the handler. Serve the page over HTTPS on an origin you added to Approved origins.
- Test instance: use a non-production instance, a test routing profile, and a flow that sets `customerPhone` with Set contact attributes. Place a call from a test number.
- Synthetic contacts: Connect's testing and simulation feature (see the Oct 26 notes in the [evaluation form post](https://www.factualminds.com/blog/amazon-connect-evaluation-form-automated-checks-2026/)) is useful for flows, not for your page. For your page, script the events with a stub `connect` object and axe.

Deployment: host the page as a static site, put the backend behind an authenticated endpoint that checks the agent's session, add the origin to Approved origins, and pin the Streams version. Re-test after every Streams or CCP upgrade.

---

## Costs (published prices, Oct 27, 2026)

From the [Connect pricing appendix](https://aws.amazon.com/products/connect/customer/pricing/appendix/), US list prices before tax:

- Voice: $0.038 per minute plus telephony. Web calling audio adds $0.010 per minute.
- Chat: $0.010 per message. Step-by-step guides: $0.010 per message.
- Customer Profiles: $0.00 for searching and reading profiles that hold only Connect data. $0.005 per profile utilized daily for imported or merged data, plus $0.005 per additional 100 objects, capped at 30% of stored profiles per day. Storage, updates, and segment creation have no charge.

Example from the appendix logic: a profile with 300 objects costs $0.015 on a day it is utilized. A Streams desktop adds no Connect license line item, but you pay for the web hosting, backend, and the engineering to maintain it. I have not priced that.

---

## Limitations

- 3P apps run only in the agent workspace, in listed Regions.
- Streams supports one browser per agent per instance.
- Imported Customer Profiles data is not real time on the AppFlow and S3 paths.
- Rule-based matching skips low-cardinality rule levels.
- Flow Lambdas stop at 8 seconds synchronous.

---

## My recommendation

Use the workspace first. Add one 3P app for the single panel agents ask for, and let guides handle scripted procedures. Choose Streams when the agent's home is a product you own and you can staff accessibility and upgrade testing. Streams gives layout control and costs you ownership of the sign-in, softphone, and test burden. A workspace app gives you less layout control and far less to maintain.

---

## What to do this week

1. Write down the one panel agents lack. If it is one panel, build a 3P app, not a desktop.
2. Check that your Region offers the Integrations menu.
3. In a sandbox, create a Customer Profiles domain with a customer managed KMS key and one S3 or Shopify source.
4. Run identity resolution in Match only and read the results before merging.
5. Clone the [artifact](https://www.factualminds.com/examples/architecture-blog-2026/connect-commerce-context/agent-workspace/README.md), run `node --test`, and point `CCP_URL` at a test instance.
6. Run axe and a keyboard-only pass on your page.

Need the build path chosen and tested against your instance? FactualMinds is an AWS Select Tier Services Partner. Start at [Amazon Connect consulting](https://www.factualminds.com/services/amazon-connect/) or [contact us](https://www.factualminds.com/contact-us/).

---

## What this post doesn't cover

- A live-instance run: the Streams page and the 3P app path were not executed against a Connect instance for this post.
- ServiceNow and Zendesk CTI adapters: not verified here.
- IAM policy JSON: action names above should be confirmed in the Service Authorization Reference.
- Banking or retail compliance: using these services does not make a deployment compliant. That depends on your controls.
- Segments, Predictive Insights, and Profile explorer: permissions exist, features not covered.
- Browser auth to your backend: choose and test your own.

---

## Related reading

- [Amazon Connect Consulting](https://www.factualminds.com/services/amazon-connect/)
- [Connect Cases CSV Export (Aug 2026)](https://www.factualminds.com/blog/amazon-connect-cases-csv-export-agent-workspace-2026/)
- [AI Customer Support Agent for eCommerce](https://www.factualminds.com/blog/ai-customer-support-agent-ecommerce-2026/)
- [AWS for Retail: Complete Guide](https://www.factualminds.com/blog/aws-for-retail-complete-guide/)

## FAQ

### Which agent UI option should we start with?
Start in the Connect agent workspace. It ships Customer Profiles, Cases, and step-by-step guides, and it accepts your own web app as a third-party (3P) app through an iframe. Build a custom Streams desktop only when the agent must live inside a product you already own and a workspace tab cannot satisfy that.

### When should we not build a custom desktop with Streams?
Skip it when the real gap is one panel of order or account data. A 3P app or a view fills that gap without you owning softphone behavior, sign-in expiry, and CCP upgrades. 3P apps are supported only in the agent workspace, so a custom desktop also gives up that extension model. You take on accessibility, release testing, and agent-state handling for the whole page.

### What could go wrong with identity resolution?
Merging too early can combine two people into one profile, and an agent then reads another customer's order history. AWS recommends enabling Match only first, reviewing the results, and setting MaxAllowedRuleLevelForMerging only after that. A rule level made only of low-cardinality attributes (more than 500 profiles) is skipped, and a dead-letter queue receives a message if you configured one.

### Can Customer Profiles ingest from NetSuite, Odoo, or JD Edwards?
Not through a documented pre-built connector. AWS documents pre-built sources for Salesforce, ServiceNow, Zendesk, Marketo, Amazon S3, Segment, and Shopify. For an ERP, land a file in S3 and use the S3 source, or write records with the PutProfileObject API from your own code. That is custom engineering.

### Do we call Connect or Customer Profiles APIs from the browser?
No for Customer Profiles and admin APIs. Browser code would need AWS credentials. Call your own backend, which holds a role scoped to one Customer Profiles domain and returns only the fields an agent needs. The browser still talks to Connect through the embedded CCP and Streams, which authenticate as the agent.

### Does the CCP iframe make our page accessible?
No. The CCP renders in an iframe, so your CSS does not apply inside it, and your page only controls what surrounds it. AWS publishes accessibility compliance reports in AWS Artifact for the Connect UI. Your own page, including focus handling on contact events and live regions, is yours to test against WCAG 2.1 AA.

### What does Customer Profiles cost in the agent workspace?
On the October 27, 2026 pricing appendix, searching profiles and reading profile objects that contain only Connect-generated data is $0.00. Profiles with imported data cost $0.005 per profile utilized daily, plus $0.005 more per extra 100 objects. Daily charges in a domain are capped at 30% of stored profiles. Confirm in your Region before you budget.

### What should we do when the profile lookup times out?
Let the contact continue. Show that no profile was loaded, give the agent a manual search, and log the reason without the customer identifier. The sample handler returns found=false with a reason of no_match or ambiguous (HTTP 200), timeout (504), or auth, throttled, misconfigured or upstream_error (502), and logs the reason and error name only. Do not block the answer button on a lookup.

---

*Source: https://www.factualminds.com/blog/amazon-connect-custom-agent-ui-customer-profiles-2026/*
