TL;DR. UAE Cabinet Resolution 56 of 2024 governs all outbound telemarketing. In Dubai, DLD Circular 02-2026 (26 Feb 2026) narrows who a brokerage is lawfully allowed to call to property owners with whom it has a documented prior business relationship. Both apply to automated systems. Resolution 56 expressly permits them, provided they follow its rules. This is what putting those rules in the database looks like what the controls are, how each one is enforced, and what the resulting audit trail contains when a regulator asks for it.
Four layers, one direction: down into SQL
- Database. Check constraints on campaigns, RLS by
org_id, atomicclaim_due_callswith FOR UPDATE SKIP LOCKED, lawful-basis gate, suppression trigger. - Compiler. Locked prompt sections with test-enforced invariants.
speakable=falseknowledge (prices, rents, service charges) never reaches the voice provider. - Runtime. Every webhook signature verified on raw body. Every dial checked against lawful basis, calling window, whitelist, suppression and the retry cap in order.
- Audit. Every state change written to an audit log with actor, before/after, timestamp. Downloadable per campaign.
The two instruments that govern this call
Outbound telemarketing to property owners is in scope of Res. 56/2024 and, in Dubai, further restricted by DLD Circular 02-2026 (26 Feb 2026). The two stack. Res. 56 sets the operating rules for the call itself (hours, disclosure, retry caps, suppression, DNCR). Circular 02-2026 sets who is lawful to call in the first place.
Res. 57/2024 then sets the administrative fines: AED 10,000 to AED 50,000 per breach, scaling with repetition. Circular 02-2026 adds a Dubai-specific sanction on top: a 3-month suspension plus an AED 50,000 fine on first breach, with licence revocation on repeat.
Res. 56 explicitly contemplates automated calling systems and permits them when they follow the rules. The design question is not whether an AI agent can make these calls. The question is whether the controls that keep it inside the rules live in a prompt (which drifts) or in the system that places the call (which does not).
DLD Circular 02-2026 in one paragraph
Issued by Dubai Land Department on 26 February 2026, the Circular prohibits licensed Dubai brokerages from contacting property owners and investors with whom the brokerage has no documented prior business relationship. The one exception is owners the brokerage has a documented prior transaction with past buyers, past sellers, past landlords and past tenants on file. Penalties are a 3-month suspension of the brokerage, an AED 50,000 fine, and revocation of the licence on repeat breaches. The primary source is the DLD PDF: dubailand.gov.ae, regulations governing communication with property owners.
Outbound calls to property owners with whom the brokerage has no documented prior business relationship are banned by DLD Circular 02-2026. A system that places such calls, AI or human, exposes the brokerage to the sanctions above. The compliant surface for AI outbound in Dubai is past-client reactivation calls to contacts on the brokerage's own CRM with a recorded lawful basis.
Cabinet Resolution 56/2024 in sixty seconds
The Resolution consolidates rules across TDRA (telecoms) and the sector regulators. For a real-estate outbound call placed by a Dubai brokerage to a documented past client, Res. 56 still governs every aspect of the call itself. The load-bearing obligations are:
- Only call from numbers registered for the purpose with the competent authority.
- Only call between 09:00 and 18:00 UAE local time.
- Screen against the National Do-Not-Call Registry before every dial.
- State the caller's identity, the represented entity, and the purpose up front.
- Disclose that the call is recorded, before any marketing content.
- Ask permission before proceeding.
- Honour a removal request in real time and permanently.
- Cap retries: no more than 1 call per day and 2 per week to the same number, counted across all campaigns.
- Never call a number that has already opted out, for any reason, in any campaign.
- Keep a per-call audit trail the competent authority can subpoena.
A large-language model can be prompted to say the right things. It cannot be trusted to enforce any of the ten items above. That is the design brief.
Where the LLM decides nothing
The single most important invariant of this architecture is that the LLM cannot be the last thing between a controlled action and the caller. Every regulated decision is made in Postgres and reviewed against a check constraint before the call ever begins:
- -- who to call: selected by claim_due_calls(), a SQL function that only returns rows that pass the lawful-basis, window, DNCR, suppression, retry-cap and whitelist gates.
- -- when to call: the calling window is checked against organizations.timezone in SQL, at claim time. If the LLM tries to schedule a callback outside the window, the row is rejected before it reaches the dialer.
- -- what to say first: the opening sentence is a locked template. Its SHA-256 hash is asserted on every deploy. Legal changes to this line require a code review, a hash bump, and a CODEOWNERS approval, not a prompt edit.
- -- what to do on removal: the “remove me” response is a state-machine terminal state (suppress_and_end); the row is inserted into a workspace-scoped suppression table with RLS, and every future claim_due_calls() filters it out. There is no path back.
The state machine
A single-prompt LLM is a bag of instructions. It can skip a step, answer an objection in the wrong stage, or fire end_call mid-qualification if the owner sounds annoyed. A state machine cannot. Andrew, the reference agent, runs on seven explicit states with enumerated transitions:
opening ─permission_yes─▶ qualification ─ready─▶ handoff ─booked─▶ recap ─▶ end_call_tool │ │ │ │─permission_no─▶ soft_bow │─not_interested─▶ objection_handling ─recovered─▶ qualification │ │ └─final_no─▶ suppress_and_end └─(intent: robot / how_got_number / remove_me at any point)──▶ objection_handling
Every non-terminal state has an unconditional edge to objection_handling . The compliance objections always reachable. Return edges are enumerated per source state so an owner who asks “where did you get my number?” mid-qualification cannot end up accidentally in the handoff state. The end_call_tool itself is scoped only to the three terminal states, so the model cannot hang up during qualification.
The three locked handlers
These are the responses that must never be paraphrased, softened, or improvised on. The state prompt embeds them verbatim; a unit test on every build asserts they appear character-for-character in the compiled prompt sent to the voice provider.
INV-6 · “How did you get my number?”
“{{data_source_statement}}. If you'd prefer not to be contacted, I can remove your number from our list right now, just let me know.”
End the turn immediately. No pivot. No pitch continuation.
INV-7 · “Remove me / don't call again”
“Done, you won't hear from us again. Sorry to bother you.”
Transition to suppress_and_end. Suppression row inserted. No further calls, no callback, no follow-up email, in any campaign in the workspace.
INV-8 · “Are you a robot? / Is this AI?”
“I am, I'm an AI assistant for {{company_name}}. Anything after this call is with {{specialist_name}} directly.”
Never deny. Never soften. Then return to the previous state.
The dialer gate
This is the function the dialer must call before every outgoing call. If it returns zero rows, no call is placed. regardless of what the LLM, the dashboard, the API, or the campaign owner would prefer. Lawful-basis screening (the Circular 02-2026 gate) is applied here too: owners without a documented prior transaction are filtered out before the row is ever claimable.
-- claim_due_calls(org, campaign) - simplified
select o.id, o.phone_e164
from owners o
join campaigns c on c.id = $2 and c.org_id = $1
where o.lawful_basis is not null -- Circular 02-2026
and now() at time zone o.timezone
between (date_trunc('day', now()) + interval '9 hours')
and (date_trunc('day', now()) + interval '18 hours') -- window
and not exists (select 1 from suppression s
where s.org_id = $1 and s.phone_e164 = o.phone_e164) -- opted-out
and not exists (select 1 from calls k
where k.owner_id = o.id
and k.created_at > now() - interval '20 hours') -- retry cap
and (c.is_demo = false
or o.phone_e164 = any(c.demo_whitelist)) -- demo mode
and o.phone_e164 not in (select number from dnc_registry) -- DNCR
order by random()
for update skip locked
limit $3;The audit trail
A regulator does not want a marketing slide about compliance. They want a per-call trace they can subpoena. Every EstateEngine Voice call writes rows in five tables that together answer the questions TDRA, RERA and DLD are trained to ask:
| Table | Question it answers |
|---|---|
| calls | When was the call, from which DID, to which E.164, and what was the outcome? |
| call_events | Which state transitions fired, in order, with timestamps? |
| transcripts | Exact words spoken by the agent and the owner, timestamped. |
| audit_log | Which admin took which action (campaign start, KB edit, suppression override) and when? |
| suppression | Every removal request, timestamped, across every campaign in the workspace. Never a call to a suppressed number, ever. |
The lawful-basis field on each owner row records how the documented prior relationship was established (past purchase, past sale, tenancy, signed representation agreement) and when, so a regulator asking “on what basis did you call this person?” gets an answer from the database, not a story from the brokerage.
What this doesn't cover
Two honest caveats worth stating. The reference implementation covers what happens between placing a call and closing it. It does not, on its own, solve:
- Carrier reputation. A UAE-mobile recipient may still see “Spam Likely” on a US-registered DID, regardless of your controls. The mitigation is bring-your-own-SIP via the brokerage's registered local operator (e& or du), supported, but a client setup step.
- PDPL data residency. Recordings and transcripts contain personal data. The default deployment stores them in Supabase's Middle East region; brokerages with stricter data-residency policies can configure a local Postgres deployment behind the same API.
How to evaluate this
The fastest way to pressure-test the controls is to try to break them. On the live browser demo you can:
- Ask “where did you get my number?”. The removal offer is spoken verbatim, then the turn ends.
- Say “remove me”. The call terminates and the number is written to the suppression table.
- Ask “are you an AI?”. The agent confirms it without softening.
- Try to push the agent into skipping qualification. The state machine will not allow the transition.
Primary sources
- DLD Circular 02-2026, Regulations Governing Communication with Property Owners and the Prohibition of Cold Callings (26 Feb 2026): dubailand.gov.ae, Circular 02-2026 (PDF).
- UAE Cabinet Resolution No. 56 of 2024 on Regulating Telemarketing Calls: uaelegislation.gov.ae, Resolution 56/2024.
- UAE Cabinet Resolution No. 57 of 2024 on Administrative Violations and Fines: uaelegislation.gov.ae, Resolution 57/2024.
The system your licence depends on
EstateEngine Voice is the compliant client-reactivation layer for Dubai brokerages. If you're fielding an AI calling proposal, a regulatory review, or a board question about your AI outreach posture under Circular 02-2026, book a walkthrough and we'll cover the controls above in your workspace.
This post is a plain-English reference, not legal advice. The official Arabic text of any UAE law, resolution or circular is authoritative. Brokerages should confirm implementation details with their RERA-appointed compliance officer before going live.