Conversational Agent Interface (CAI)

The AES standard for integrating an external conversational agent provider into a customer's digital channels, with AES as the system of record.

1. Overview

The Conversational Agent Interface (CAI) is the OMB Cloud AES standard for integrating an external conversational agent provider into a customer’s digital channels. It covers inbound web forms, web chat and messaging channels, and the handling of the resulting conversation through to a booked appointment or a recorded outcome.

The division of work is deliberate and narrow. The Provider supplies the conversational intelligence. AES supplies the flow of contacts, the routing, and the permanent record. Everything a customer sees, reports on, and acts upon continues to live in AES.

The company implementing this interface is referred to throughout as the Provider. Each Provider is issued a provider_code and a set of credentials at onboarding.

This specification is versioned and shared across all Providers. Environment-specific values — provider code, catalog, credentials, authorised addresses — are issued separately in a private annex.

2. Roles and responsibilities

ResponsibilityAESProvider
Capture of the contactYes—
Resolution of the destination unitYes—
Selection of the origin number or identity—Yes
Conversation with the contact—Yes
Closing the appointment—Yes
Recording and retention of the conversationYes—
Commercial follow-up thereafterYes—

2.1 Interfaces

IdDirectionMethodPurpose
AAES → ProviderPOSTDelivery of contact jobs
BProvider → AESPOSTReturn of conversation, appointments and outcomes

Both directions are push. Neither party polls the other, and no read endpoint is exposed under this interface. This keeps latency low, removes the need for scheduled synchronisation, and means a Provider integration has exactly two moving parts.

3. Lifecycle

  1. Contact      Submits a form or writes on a digital channel.

  2. AES          Creates the record, resolves the destination unit and
                  assigns a lead_id that accompanies the relationship.

  3. AES → Prov.  [Interface A] Delivers the contact job with the unit
                  and the context of the request.

  4. Provider     Selects the origin number for that unit and starts
                  the conversation.

  5. Prov. → AES  [Interface B] Returns the conversation as it happens,
                  and the result: appointment booked or reason closed.

  6. AES          Records both against the lead, stamped with the
                  provider_code. The customer continues follow-up.

The destination unit is resolved at the moment of capture, where the landing page, the campaign and the requested location are known. It travels in the branch_code field of every job, so a Provider never has to maintain or update routing logic as a customer opens new locations.

4. Interface A — Contact jobs

POST {provider_endpoint}/contact-jobs
Content-Type:    application/json
X-CAI-Source:    aes
X-CAI-Signature: sha256=<hmac_hex>
X-CAI-Timestamp: 1787923271

AES signs its outbound requests with the same scheme described in section 6, using the opposite secret of the pair. The Provider should verify them exactly as AES verifies the Provider’s: same algorithm, same 300 second window, comparison in constant time.

AES delivers each contact the Provider is expected to handle, at the moment of capture.

4.1 Request body

{
  "lead_id":        "AES-38-104772",
  "event_id":       "job_9f2c1a8e4b",
  "branch_code":    "ACME-NORTH",
  "city":           "Monterrey",
  "contact": {
    "name":         "Maria Fernanda Rios",
    "phone_e164":   "+5218112345678",
    "email":        "mfrios@example.com",
    "language":     "es-MX"
  },
  "origin": {
    "channel":      "landing_form",
    "source":       "example.com/north/service",
    "campaign":     "spring-north",
    "captured_at":  "2026-08-27T14:02:11-06:00"
  },
  "brief": {
    "intent":       "book_appointment",
    "notes":        "Requested an evening slot."
  },
  "callback_url":   "https://omb.cloud/app/api/cai_events.php"
}

4.2 Fields

FieldTypeReq.Description
lead_idstringYesIdentifier of the contact in AES. Returned unmodified on every Interface B event. This is what keeps the conversation bound to the record.
event_idstringYesUnique per job. Enables safe retries. A repeated value must be ignored.
branch_codestringYesDestination unit. Determines the origin number. Catalog issued per deployment.
citystringNoHuman-readable reference, for reporting and conversation context.
contact.namestringYesName as declared by the contact.
contact.phone_e164stringYesE.164 format. Primary contact key on both platforms.
contact.emailstringNoPresent when supplied by the contact.
contact.languagestringNoPreferred language. Defaults to the environment locale.
originobjectNoCapture provenance, so the conversation opens in context.
brief.intentenumNoDetected intent. See Annex A.
brief.notesstringNoWhat the contact asked for, summarised by AES.
callback_urlstringYesDestination for Interface B events.

4.3 Expected response

HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "provider_job_id":      "prv_77219",
  "assigned_number_e164": "+528112345678"
}

Reporting the assigned number lets AES attribute inbound messages from that contact correctly, and maintain a single conversation if the contact later returns through another channel.

5. Interface B — Conversation events

POST https://omb.cloud/app/api/cai_events.php
Content-Type:    application/json
X-CAI-Provider:  {provider_code}
X-CAI-Signature: sha256=<hmac_hex>
X-CAI-Timestamp: 1787923271

A single endpoint receives everything the Provider returns. It is designed for real-time writes, signed and idempotent, so a Provider can send and retry without risk of duplication.

5.1 conversation.message

One event per message, in both directions, as it happens. The full record is what allows the customer to see the agent’s work as it happened and to attribute the resulting appointments precisely.

{
  "event":            "conversation.message",
  "event_id":         "evt_4b81c07f",
  "lead_id":          "AES-38-104772",
  "provider_job_id":  "prv_77219",
  "channel":          "whatsapp",
  "from_number_e164": "+528112345678",
  "direction":        "outbound",
  "author":           "agent",
  "text":             "Good afternoon Maria Fernanda, I am writing from...",
  "occurred_at":      "2026-08-27T14:04:39-06:00"
}

Event fields. event and event_id are required on every event; the rest depend on the type:

FieldPresenceDescription
eventRequiredEvent type
event_idRequiredUnique event identifier, up to 120 characters
lead_idOptionalThe identifier delivered in the assignment, unmodified
provider_job_idOptionalThe Provider’s own identifier
channelOptionalMessage channel; see A.6
from_number_e164OptionalOrigin number in E.164
directionOptionalinbound or outbound
authorOptionalWho wrote it; see A.3
textOptionalMessage text
occurred_atOptionalWhen it happened, ISO 8601 with offset

5.2 Appointment events

Sent on booking, rescheduling or cancellation. AES records the appointment and reflects it on the corresponding unit’s board.

{
  "event":        "appointment.booked",
  "event_id":     "evt_4b93a112",
  "lead_id":      "AES-38-104772",
  "branch_code":  "ACME-NORTH",
  "scheduled_at": "2026-08-29T11:30:00-06:00",
  "service":      "first_visit",
  "notes":        "Prefers mornings.",
  "occurred_at":  "2026-08-27T14:11:02-06:00"
}

Accepted values for event: appointment.booked, appointment.rescheduled, appointment.cancelled.

5.3 job.closed

Sent when handling ends without an appointment. It lets the customer resume through other means and prevents duplicate outreach to the same contact.

{
  "event":       "job.closed",
  "event_id":    "evt_4ba7d290",
  "lead_id":     "AES-38-104772",
  "outcome":     "no_answer",
  "attempts":    4,
  "occurred_at": "2026-08-29T18:00:00-06:00"
}

5.4 Idempotency and retries

CodeMeaningSuggested action
202Event accepted, or discarded as a duplicateNone
400Invalid schemaDo not retry. Review the body
401Invalid signature, outside the window, unrecognised provider, or unauthorised originDo not retry. Check credential, clock and registered origin
413Body larger than 256 KBDo not retry. Reduce the event
429Request cap reachedRetry after the value of Retry-After
5xxTemporary unavailabilityRetry with exponential backoff for up to 24 h

Every event carries a unique event_id (up to 120 characters). AES discards repeats and answers 202 with {"ok": true, "duplicate": true}, so a retry never produces a duplicate record. In practice, any 2xx means accepted.

A lead_id AES does not recognise is not an error: the event is accepted with 202 and logged for reconciliation between both teams.

6. Authentication

Both directions are signed with HMAC-SHA256 over the request body, using an independent shared secret per direction. This is the same mechanism AES operates with its messaging and payment integrations.

signature = HMAC_SHA256(secret, timestamp + "." + raw_body)
header    = "sha256=" + hex(signature)

6.1 Worked example

Verify your implementation against these exact values before writing any integration code.

secret     cai_test_5f3a9c21b7e04d8a
timestamp  1787923271
body       {"event":"conversation.message","event_id":"evt_4b81c07f","lead_id":"AES-38-104772"}

signature = HMAC_SHA256(secret, timestamp + "." + body)

X-CAI-Signature: sha256=a893b6460bbb5063910f16ed0b8bbaa44204ea83d9a0ceaa6ac539e0d7bd9f1a

The signed string is the timestamp, a literal dot, and the raw body exactly as transmitted: no re-serialisation, no whitespace changes, no key reordering. That is where most implementations lose time.

ElementDefinition
Validity window300 seconds, to limit replay exposure.
CredentialIssued per Provider and per environment. Identified by the X-CAI-Provider header.
Source addressesThe Provider supplies its egress IP addresses; AES registers them as authorised origins.
RotationCoordinated between both teams, with an overlap window so service is not interrupted.
TransportTLS 1.2 or above in both directions.

7. Environments and unit catalog

Each deployment has its own environment: a provider_code, a credential pair, and a catalog of branch_code values with their human-readable names. AES maintains the catalog and updates it as the customer opens new units. The Provider maps each code to its origin number.

Because routing travels with the job, a new unit requires no integration change on either side. The Provider adds one row to its mapping; nothing else moves.

The catalog, the credentials and the authorised addresses are issued in the private annex that accompanies this specification for each deployment.

Alongside the production credentials, a pair of test credentials is issued: they point to the same URLs and use the same signing scheme, but their data lands in an isolated test space. Everything described in this document can be exercised end to end with them before touching real data, including receiving a sample assignment emitted by AES.

8. Scope of version 1.0

The first version concentrates on what produces results from day one: reaching the contact, holding the conversation, and closing the appointment. Keeping it narrow allows both parties to reach production quickly and with low risk.

8.1 Included

  • Real-time delivery of contacts from every digital channel.
  • Routing by unit, resolved by AES and delivered with each job.
  • Recording of the full conversation, in both directions.
  • Appointments booked, rescheduled and cancelled.
  • Outcomes with reason, to coordinate follow-up.
  • Attribution of every result to the Provider’s code.

8.2 Planned for later versions

  • Additional channels, as results are validated on those already in service.
  • Availability by unit, so the agent can offer slots that are already confirmed.
  • Post-appointment events, attendance and follow-up, to close the measurement loop.
  • Extended reporting, based on what both teams identify as useful in operation.

8.3 Not part of this interface

CAI is a push interface in both directions and exposes no read endpoints. Operational figures a Provider needs for its own reporting are delivered by AES on an agreed schedule, as described in section 9.

In regulated sectors, records held in the customer’s operational system of record — clinical files, financial histories, case documents — remain outside this interface, since they play no part in booking an appointment. Where a specific data point is genuinely required for a conversation, it is assessed case by case with the customer.

9. Reporting and data protection

9.1 Reporting

AES delivers a periodic report of the Provider’s own operation: jobs received, time to first contact, conversations held, appointments generated and outcomes. Frequency and fields are agreed between both teams.

Because AES builds it, the report is computed on the same base the customer sees. Service measurement and customer measurement always agree, and there is no reconciliation of figures across platforms.

9.2 Personal data

The Provider acts as a data processor on the customer’s behalf: it uses the information for the purpose of this interface, does not transfer it to third parties, does not use it for any other purpose including model training, and deletes it at the end of the contractual relationship.

AES retains the complete record of every conversation as part of its custody obligations to the customer. This also guarantees service continuity in the event of an incident on either platform.

10. Service levels

Baseline targets. Adjusted per deployment against the Provider’s actual operating model.

ItemTarget
First contactWithin 5 minutes of receiving the job, during operating hours.
Message deliveryWithin 60 seconds of each message occurring.
Appointment deliveryAt the moment of confirmation with the contact.
Synchronous web chat replyUnder 5 seconds. AES maintains a continuity response so no contact is left unattended if the service is unavailable.
RetriesExponential backoff up to 24 hours on either side.
Endpoint availability99.5% monthly, both directions.

11. Becoming a Provider

  1. Confirm the schema in this specification.
  2. Supply the contact-jobs endpoint documentation and egress IP addresses.
  3. Supply the origin numbers or identities available per region.
  4. Exchange secrets in the test environment.
  5. Run end-to-end tests against a test environment issued by AES.
  6. Pilot on a single unit for two weeks.
  7. Roll out to the remaining units.

Piloting on one unit lets both teams tune script, timing and data quality at controlled volume before opening the rest.

12. Versioning

This document describes version 1.0. New fields may be added without notice and unrecognised fields should be ignored. No field is removed or changes meaning within the same major version. Scope extensions are agreed between both teams and produce a new version.

VersionDateChanges
1.02026-08-27Initial published version.

Annex A — Enumerations

A.1 origin.channel

landing_form | contact_form | webchat | whatsapp_button | phone | referral

A.2 brief.intent

book_appointment | pricing_information | service_information |
reschedule | follow_up | other

A.3 author

agent    Provider conversational agent
contact  The person being contacted
human    Provider human operator

A.4 outcome

ValueMeaning
no_answerNo reply after the configured attempts
not_interestedDeclined
wrong_numberThe number does not belong to the contact
callback_laterAsked to be contacted at another time
opted_outAsked not to be contacted again

A.5 Formats

TypeFormatExample
TelephoneE.164+5218112345678
Date and timeISO 8601 with offset2026-08-27T14:02:11-06:00
LanguageBCP 47es-MX
EncodingUTF-8application/json

A.6 channel and direction (Interface B)

channel:    whatsapp | webchat | sms | phone | email
direction:  inbound | outbound

Contact

For onboarding as a Provider, or questions about this specification, write to developers@omb.cloud.