Cadence

9 undocumented traps in Google’s RBM API

Last updated 23 August 2026. Found by taking one agent from creation to a live carrier launch on four US networks. Every item here is reproducible, several cost days, and three cannot be undone.

The short version

  1. Requesting verification permanently freezes the agent’s entire public profile — and it fires on request, not on completion.
  2. Palette PNGs are re-encoded and destroyed. Ours went in with 128 colours and was stored with 6.
  3. contact.title is required even though the schema marks it optional.
  4. The launch state machine has no LAUNCH_STATE_FAILED. Branch on it and a rejection reads as still launching, forever.
  5. launchDetails is a complete set, not a delta. A second launch request silently drops every existing launch.
  6. requestVerification needs five required fields, and the partner and the brand are different parties.
  7. Launch requests to major US carriers return 403 before you can submit, contradicting Google’s own support guidance.
  8. Agent branding is cached on the device for 7 days, and neither deleting the thread nor toggling RCS clears it.
  9. Agents cannot be deleted. Every mistake above is permanent.

1. Verification freezes everything, on request

Google’s reference marks logoUri, heroUri and displayName as “not modifiable after agent verification”. Both halves of that are misleading. The real locked set, from their own rejection:

Contains invalid field paths for agent after verification:
  description, logo_uri, hero_uri, color, privacy, terms_conditions,
  emails, phone_numbers, websites

That is the whole info screen. And “after verification” means after it is requested: an agent sitting at VERIFICATION_STATE_PENDING already refuses all of it, while an agent that never requested still accepts a PATCH. Since agent deletion is deprecated, a wrong profile is a support ticket rather than an edit. Get the profile final before you request verification — it arrives earlier than anyone expects.

2. Palette PNGs are silently re-quantized

A hero uploaded as a palette-mode PNG (colour type 3, 128 colours) came back from agent-logos.storage.googleapis.com with six colours, which erased every fine line in the artwork. A second agent’s hero, an RGB PNG, was stored byte-identical with all 2691 colours.

Nothing warns you, the GET returns your URL rather than theirs, and by the time a handset shows it the asset may already be frozen. Export true-colour PNG or JPEG, never palette, and compare the stored copy against your source before requesting verification.

3. A required field the schema calls optional

Contact.title carries no “Required” marker. requestLaunch returns Agent’s contact title is required. The endpoint is the authority, not the page.

4. Branching on an enum value that does not exist

The documented LaunchState enum is UNSPECIFIED, UNLAUNCHED, PENDING, LAUNCHED, REJECTED, SUSPENDED. There is no FAILED and no DECLINED. Code that branches on those — ours did — sends the one value that means no, REJECTED, into the default case. A carrier rejection then reads as a launch still in flight for as long as anyone is willing to wait. VERIFICATION_STATE_FAILED does not exist either.

5. launchDetails is a set, not a delta

Launching on a second carrier means sending every region you are already launched on plus the new one. Send only the new one and the others are dropped, and the request succeeds. This is stated in the docs, in one sentence, and it is the kind of thing you find out months later.

6. Verification needs five fields, and two different parties

AgentVerificationContact requires partnerName, partnerEmailAddress, brandContactName, brandContactEmailAddress and brandWebsiteUrl — all of them. The partner is you; the brand contact is someone at the customer who can confirm you act for them, and Google emails that address a mandatory authorisation request. A shared mailbox is a rejection. Note also that verification is not performed until a launch is requested, so waiting for “verified” before requesting launch is a wait for nothing.

7. The majors 403 before you can even submit

Google support told us submitting a launch request without a commercial agreement is sanctioned and is how you begin contractual discussions with a carrier. The API disagrees:

This network, United States: T-Mobile, requires an agreement with the
carrier to submit a launch request.

Same for AT&T, Verizon, Dish, Spectrum and Xfinity. Tracfone, Cape, ClearSky and Interop accepted the identical request. There is no way to open the conversation through Google, and no empirical path to learning a carrier’s bar — you cannot even fail informatively. AT&T additionally routes through its own gateway rather than Google’s, which is a separate integration.

8. Branding is cached on the device for seven days

Update a logo and the handset keeps showing the old one. Deleting the thread does not clear it. Toggling RCS does not clear it. Re-inviting the tester does not clear it. It is a seven-day client-side cache, and on Android you can force a refresh: search *xyzzy* in Google Messages to reveal the debug menu, then Debug → RBM → Reload chatbot information. There is no iOS equivalent.

9. None of it can be undone

Agent deletion is deprecated for RBM — it is a support ticket, not an API call. Hosting region and use case are fixed at creation. Billing category is fixed at launch. The whole profile freezes on verification request. Brands can be deleted; agents cannot.

Why we wrote this down

We hit all nine shipping Cadence, and every one of them was found by a rejection rather than by reading. Our own readiness check now enforces each one before a submission can be made, because a clean first submission clears in days and a rejection costs weeks.

You can run it against your own domain, free and without an account: cadencercs.com/readiness.html. It crawls your site, validates the disclosures carriers actually check, and generates the copy for whatever is missing.

Corrections welcome — support@cadencercs.com. Cadence is a service of Salus, Inc.

These are the traps inside the API. The one outside it is bigger: an approved agent still reaches nobody until a carrier agreement exists, and Google does not broker one. Once it does, replies can still vanish while sending looks fine, and your bill will not match your quote — RCS is billed by conversation, not by message.