Heavy template — auto-mapped from HubSpot. You can edit this expression directly, or switch to medium mode for a guided builder.
Event source
HubSpot · deal stage change
HubSpot · contact property change
celliq · scheduled cron
Calendar · meeting created
Filter expression
Test data
▶ Run filter against last 30d events
Last run: 14 deals matched · 12 contacts not previously called · 2 inside 30d window (excluded)
Audit log
● 2026-05-07 14:32 · created by James
● 2026-05-07 16:21 · amount threshold £3k → £5k by Sarah Lin
● — no other changes —
Each row maps a field in your CRM to a variable the agent sees in its pre-call brief.
From your CRM Used in the brief as
Contact's full name
HubSpot · firstname + lastname
→
Contact name
{{contact.name}}
edit · remove
Job title
HubSpot · jobtitle
→
Role
{{contact.role}}
edit · remove
Company name
HubSpot · company.name
→
Account
{{account.name}}
edit · remove
Deal close date
HubSpot · deal.closedate
→
Signup date
{{account.signup_date}}
edit · remove
Account manager's email
HubSpot · deal owner
→
AM email
{{account.am_email}}
edit · remove
Last CSAT call summary
celliq history · last outcome
→
Last call summary
{{contact.last_call_summary}}
edit · remove
+ add field
Auto-built from your Conversation . Two channels: one for every call (the team summary), one for escalations only. Each post auto-renders from the captured items — toggle anything off you don't want surfaced.
Where Slack posts go
Default channel
#cs-team — every completed call
#revenue
#general
Escalation channel
#cs-escalations — when call needs human follow-up
#leadership
(same as default)
Escalate when
When CSAT score is 5 or below
When CSAT score is 7 or below
When At-risk flag is true
When Renewal intent is negative
Custom condition…
Never escalate (single channel only)
Conditions reference fields from your Conversation .
What gets posted
Include
Each captured item becomes a line in the Slack post. Same toggles for default and escalation channels.
Default channel preview
channel #cs-team
posted by celliq · 14:32
📊 CSAT call · acme.co
Sarah Lin · Head of Customer Success
Score: 9 / 10 ⭐
What's working:
Fast support Easy onboarding
Renewal intent: positive · plans to expand seats
"Strong CSAT call. Onboarding praised; support team called out as fast. Customer wants to expand seats next quarter."
Escalation preview
channel #cs-escalations
posted by celliq · 14:28
🚨 Escalation · globex.io
Tom O. · Operations Lead
Score: 3 / 10
What needs attention:
Two open tickets unresolved for 3 weeks Support response time
"Multiple unresolved tickets. Renewal at risk if response time doesn't change."
Not configured. CSAT calls don't typically need calendar updates — but you can attach a calendar event after a low-score escalation so the AM has a follow-up booked. Optional.
Trigger
— off (no calendar action) —
On every call
On escalation only (score ≤ 5)
On positive renewal intent
Event type
— pick a trigger first —
Attendees
HubSpot · acme.co
workspace 8421 · token refreshed 14m ago · scopes: contacts, deals, companies, timeline
30
contacts written today
230ms
typical write speed
Activity (timeline note)
auto-built from your Conversation
Every call leaves a timeline note on the contact + deal record so AMs see the result inside HubSpot. The note's content auto-renders from your Conversation — toggle which captured items appear in the body, no template syntax to maintain.
Create activity
On every completed call
When CSAT score is 5 or below
When CSAT score is 7 or below
When At-risk flag is true
Custom condition…
Off — no activity created
Include
Each captured item becomes a section in the activity note.
Preview
on acme.co · contact: Sarah Lin · deal #5491
type Note (timeline activity)
celliq · CSAT call · 9/10
"Strong CSAT call. Onboarding praised; support team called out as fast. Customer wants to expand seats next quarter."
Recorded by celliq integration user · linked to contact #1234 · Wed 7 May 14:32
Activity type
Note (timeline activity)
Task (assigned to AM, follow-up due 24h)
Call log (call.body)
Linked to
contact + deal · auto-resolved from the call's pre-call brief
Recorded by
celliq integration user
The contact's account manager
Property mappings
3 mapped · all idempotent
1
CSAT score outcome.score → HubSpot contact's CSAT score field
number 1–10
writes on every call
safe to retry
From the call outcome
→
HubSpot contact · CSAT score
transform
none — written as-is (1 to 10)
idempotency
if the contact already has the same score from this call, the write is skipped (won't double-write)
If something fails
retry with backoff for up to 24 hours · then drops into your Inbox
edit →
2
At-risk flag outcome.escalation_required → HubSpot deal's At-risk field
true / false
writes only when escalated
safe to retry
From the call outcome
→
HubSpot deal · At-risk = true
transform
if call was escalated → set deal At-risk = true · if not escalated → leave deal alone (won't undo prior at-risk flags)
condition
only writes on escalation · low scores from later calls don't undo at-risk flags from earlier calls
also creates
HubSpot task on the deal · "Follow up: CSAT escalation from {{contact.name}}"
idempotency
if the same call already created a follow-up task for this deal, no duplicate is created
edit →
3
Call summary outcome.raw_summary → HubSpot contact's Last CSAT summary field
text · up to 280 characters
writes on every call
safe to retry
From the call outcome
→
HubSpot contact · Last CSAT summary
edit →
+ add property mapping
test against sandbox
view all available HubSpot fields
Recent writes
last 7 · 100% success rate
14:32
contact:1234
csat_score = 9
✓
230ms
14:32
contact:1234
last_csat_summary updated
✓
180ms
14:32
deal:5491
timeline activity created
✓
312ms
14:28
deal:5678
at_risk = true
✓
195ms
14:28
deal:5678
task created · "Follow up: CSAT escalation"
✓
240ms
14:28
contact:5678
csat_score = 4
✓
210ms
14:11
contact:9012
csat_score = 8 · already-current (skipped)
↺ idem
15ms
Replays of completed writes are no-ops (key: call_id, hubspot_object_id, property ). Failed writes retry exp-backoff for 24h, then DLQ to your Inbox + Today queue.
What this agent captures from each call. Each row is one piece of structured information saved to your CRM, Slack, or email. The tag on each row tells you
how it's captured — asked directly, listened for, computed, or generated after the call. The actual
questions the agent asks live in
State machine ; this page is about the data shape and where it lands.
1
CSAT score Asked · step 1 (Ask score)
A number from 1 to 10. Saved to HubSpot's CSAT score field. Required — call goes to Review queue if missing.
customise →
2
What's working Asked · step 2 (when score ≥ 8)
A list of positive feedback themes the customer mentions when prompted. Optional — saved to Slack #cs-team summaries.
customise →
3
What needs attention Asked · steps 3 & 4 (when score ≤ 7)
A list of pain points or improvement areas the customer raises when prompted. Optional — saved to HubSpot's CSAT summary field.
customise →
4
At-risk flag Computed automatically
Set to true when the CSAT score is 5 or below — never asked, just derived. Saved to HubSpot's deal At-risk field, and posts a message in Slack #cs-escalations .
customise →
5
Renewal intent Asked · step 5 (Wrap)
Positive, negative, or unsure. Asked at the end of the call. Saved to HubSpot's deal Renewal signal field.
customise →
6
Do-not-call request Listened for · throughout compliance lock
Set to true if the customer says they don't want to be called again — never asked directly, only listened for. Adds the contact to the suppression list. Cannot be removed .
view (locked)
7
Call summary Generated after the call
A short text recap (up to 280 characters), produced by the AI once the call ends — not asked, not listened for. Pushed to HubSpot, Slack, and email.
customise →
Of triggered events, which qualify? Filter is evaluated server-side before the agent is invoked — non-matching events are dropped (no cost, no call).
Quick segment
Custom (use expression below)
Onboarded customers · last 30 days
Renewal at-risk (deal stage 'risk')
High-ARR accounts (£10k+ MRR)
EU-only customers
+ save current expression as segment
Filter expression
Test data
▶ Preview against last 30d events
14 triggered → 12 qualified → 2 filtered out (called within 30d)
When can this agent dial? Standard policy: 09:00–17:30 prospect's local TZ, weekdays. Calls outside the window are queued for the next valid slot.
Start time
End time
Timezone source
Prospect's local TZ (from CRM)
Workspace TZ (Europe/London)
Fixed: UTC
Holidays
Skip prospect's national holidays
Dial through holidays
Skip workspace holidays only
Quiet hours
Honour CRM "do not contact" hours
Strict — no calls 19:00–08:00 prospect TZ
Off — only main window applies
Sources we check before every dial. Adding a source means we check it on every call — slower for high-volume agents, but tighter compliance posture. At least one source is required (compliance).
✓
Internal suppression list
147 entries · auto-add on `dnc_requested = true`
view list →
✓
HubSpot DNC property
contact.hs_email_optout · synced every 15 min
configure →
○
UK National TPS
not enabled · ~5,200,000 numbers · adds 80ms per dial
enable →
○
US TCPA · National DNC
not enabled · adds ~120ms per dial
enable →
○
Custom CSV upload
not enabled · refresh weekly
upload →
DNC checks run pre-dial in parallel — total added latency is the slowest source, not the sum. A `dnc_requested = true` outcome auto-adds the contact to internal suppression (compliance policy).
Compliance disclosures. All five required disclosures are baked in — they fire automatically and cannot be removed. You can edit the wording for the two scripted ones (AI disclosure, recording disclosure). The other three run server-side.
AI disclosure
fires within first 3 turns · cannot be skipped
"Just so you know, I'm an AI assistant from {{account.name}} — we use this to keep up with our customers more often than we could otherwise."
edit wording
Recording disclosure
fires before any audio is captured
"This call is being recorded for quality and so we can pass any specific feedback back to {{account.am_email}} . Is that OK?"
edit wording
"Are you human?" intent
auto-routes to human disclosure · default wording (read-only)
DNC honour
runs pre-dial · sources configured separately
Calling window
enforced server-side · configured separately
Our compliance policy forbids removing or weakening these checks. Each gate firing writes a compliance event to the audit trail.
Voice profile. ElevenLabs voice models. Sample each to compare warmth, clarity, and brand fit. Premium voices use the higher-fidelity model.
Sarah
female · UK · warm
▶ play sample
James
male · UK · professional
▶ play sample
Jordan
non-binary · US · calm
▶ play sample
Rachel
female · US · expressive · premium
▶ play sample
Adam
male · US · authoritative
▶ play sample
+ clone
use a custom voice
upload audio →
Barge-in
Allow user to interrupt
Block until agent's turn ends
Tone, pacing, empathy posture. Affects the speaking style and the prompt-system tuning. Doesn't change the words; changes the delivery and the LLM's behavioural prior.
Persona
CSAT operator (warm, professional, concise)
SDR (energetic, brisk, persistent)
Customer success (calm, patient, problem-solving)
Custom — write your own description
Stability affects per-turn audio length and the LLM's behavioural prior. Lower values feel more human; higher values feel more consistent.
Auto-built from your Conversation . Every captured item becomes a section in the email — no template syntax to maintain. Toggle anything off you don't want in the AM's inbox; preview updates instantly. Drop into raw template editing only if you really need to.
Sent to
The contact's account manager (from HubSpot)
A fixed address
Round-robin from a list
Cc
Send when
Every completed call
When CSAT score is 5 or below (escalations)
When CSAT score is 7 or below
When CSAT score is 9 or above (delight)
When At-risk flag is true
When Renewal intent is negative
When Renewal intent is unsure
Custom condition…
Off — don't send emails
Conditions reference fields from your Conversation . Add a captured field there and it appears here automatically. Rename one and this rule updates with it.
Include from the conversation
Each captured item becomes a section in the email. Toggle off anything you don't want in the AM's inbox.
Preview
From celliq notifications
To bulat@aictrl.dev
celliq · CSAT call · Sarah Lin · 9/10
Hi James,
CSAT call with Sarah Lin (Head of Customer Success at acme.co ).
Score: 9 / 10
"Strong CSAT call. Onboarding praised; support team called out as fast. Customer wants to expand seats next quarter."
What's working:
Fast support Easy onboarding
Renewal intent: positive · plans to expand seats next quarter
Custom intro
Custom sign-off
From
celliq <no-reply@notifications.celliq.ai>
Reply via the account manager's address
What happens to fan-out writes that fail. Applies to every destination (HubSpot, Slack, email, calendar). Idempotency keys mean retries are safe.
Strategy
Exponential backoff
Linear backoff
Fixed interval
No retry (DLQ on first fail)
DLQ destination
Inbox + Today queue
Slack #cs-team
Email to {{account.am_email}}
Webhook (custom URL)
Drop silently (audit-logged)
Last 7 days: 412 successful writes · 3 retries (all eventually OK) · 0 dropped to Inbox. Typical write speed: 230ms.
Every change to this agent. Versions are auto-created when any cell changes. You can restore any prior version (preserves the current as a new draft, never overwrites silently).
v1.4 · current
2026-05-08 14:00
Sarah Lin
Slack routing
default channel: #revenue → #cs-team
v1.3
2026-05-08 12:30
James S.
Trigger
amount threshold: deal.amount >= 3000 → deal.amount >= 5000
↶ restore this version
v1.2
2026-05-07 16:21
James S.
Voice
voice profile: UK · neutral · ElevenLabs "Daniel" → UK · calm · ElevenLabs "Alice"
stability: 70 → 55
↶ restore this version
v1.1
2026-05-07 15:05
James S.
Brief sources
+ added celliq.history.last_csat_outcome → {{contact.last_call_summary}}
Audience filter
language predicate: + added contact.preferred_language = 'en'
↶ restore this version
v1.0
2026-05-07 14:32
James S.
Created
agent created from PA-001 (CSAT Survey) template · all 18 cells inherit template defaults · heavy path · auto-mapped from connected systems
Audit history is retained for 7 years. Each version snapshot includes the full agent configuration; restoring is non-destructive (creates a new version with the prior contents).
Pre-call research and enrichment. Async fetch of public + permitted data about the contact and their company before the agent dials. Output fields land in the brief alongside CRM data, usable in opening lines and probe prompts ({{company.recent_news}} ).
Research engine · Firecrawl + Apify
2 active sources · cache TTL 24h · last warm 14m ago · 73% cache hit rate today
Roadmap. Today: Firecrawl (general web) + Apify (LinkedIn). Coming: a celliq-internal researcher that caches a knowledge graph per business + contact. External vendors keep firing only for new accounts and stale entries; cache hit rate keeps climbing as your account base grows.
Active sources
2 of 5 enabled
1
Company website— reads pages on the customer's site
Firecrawl
2 pages deep
~8 seconds
refreshed daily
Uses your HubSpot company website URL
→
Captures 4 things
Pages we look at
Homepage · About · Pricing · Blog (last 5 posts) · News · Press
What we capture
Recent news · What they do · Tech stack · Press coverage
If a page fails
We log it · the call still happens with whatever info we have
Last 7 days
214 of 218 successful · 4 timed out · 156 served from cache (72%)
collapse
2
LinkedIn company page— pulls company info from LinkedIn
Apify
company profile
~14 seconds
refreshed weekly
Matches by company name + website
→
Captures 3 things
What we capture
Employee count · Recent funding · Industry
Refresh
Once a week (LinkedIn changes slowly)
Last 7 days
198 of 218 successful · 14 no match (private or missing) · 6 rate-limited
edit →
Available
3 sources · click to enable
○
LinkedIn contact page Apify · GDPR-sensitive
Adds: contact.linkedin_summary, recent_role_change · 7d cache · enable per opt-in segment only
enable →
○
Crunchbase requires API key
Adds: company.funding_stage, company.last_round, company.investors · 7d cache
connect →
○
News + press releases Firecrawl + RSS
Adds: company.last_30d_news (deduped) · 12h cache
enable →
+
Custom URL fetcher per-call override
Pull a specific URL or pattern per call (e.g. {{contact.referral_link}}) and extract structured fields
build →
Policy
applies to all sources
Latency budget
90 s · per source
Sources fetch in parallel; budget is the slowest source, not the sum
Research depth
Standard · 2 sources
Light · Standard · Deep — auto-skips slowest source if budget tight
Cache TTL
24 h default · per source override
Same domain within window = free re-use
If something fails
Proceed with baseline brief
Alternative: skip call · queue retry
Recent runs
last 7 · 96% success rate
14:32
acme.co
2 sources · 4 things captured
✓
12s
14:11
pivot.co
2 sources · cache hit (warmed 4h ago)
↺ cache
0s
13:55
hooli.com
website ✓ · LinkedIn timeout
⚠ partial
14s
13:42
northwind.com
2 sources · 5 things captured
✓
11s
13:30
initech.com
DNC pre-empted · research skipped
— skipped
—
13:18
globex.io
2 sources · cache hit (warmed yesterday)
↺ cache
0s
12:45
stark-industries.com
2 sources · 6 things captured
✓
15s
External sources Firecrawl and Apify are registered as sub-processors for this workspace. Internal cached researcher (planned) will reduce dependency over time but not eliminate it for new accounts.
Editor for this cell isn't built in this mock.
In production, every cell opens its own editor in this slide-over — same pattern as Trigger, Brief sources, Slack routing, Calendar update, and State machine. Prompts deep-edit drops to the layered config view (layer.html).