Connect by JBRH Open Connect

Follow-ups from a call

When a caller and the voice agree on something that happens later, the call ends with a dated commitment rather than a sentence in a transcript. schedule_follow_up takes the promised words, voice_engine.due_at turns them into a time in the line's own timezone, and follow_up_channel decides whether that is a call-back or work for a person.

Status
Available What this means
Audience
both
Channels
phone
In the app
#/follow-ups, #/calls
Last verified
Product version
6.3.2

From spoken words to a dated row#

The tool the voice calls is schedule_follow_up, and it is given more than the promise: it receives the caller's last lines and the voice's own. That context is not for the record, it is for the check — the integrity rules that decide whether this promise may be booked at all need to see what was actually said, not a summary of it.

What comes out is an ordinary Follow-up: a dated commitment on a channel, with a reason. It appears alongside follow-ups created from email or from a person typing one in, it is worked by the same drain, and it shows on the relationship's timeline. A phone call is where it came from, not a separate kind of thing it is.

The words that become a time#

voice_engine.due_at converts the promised phrase into a due time in the line's timezone — not the server's, and not the caller's, because the line is the thing whose business hours and staffing the call-back has to fit.

What was saidDue at
"in 10 minutes"Ten minutes from the end of the call
"tomorrow 11am"11:00 the next day, line timezone
"Friday 3pm"15:00 on the coming Friday
"today evening"That evening
Nothing usable11:00 tomorrow

The fallback is a deliberate choice and worth understanding. A promise with an unparseable time is still a promise, and dropping it because the phrasing was awkward would lose the commitment entirely. 11:00 tomorrow is early enough to be useful and late enough that nobody is rung at an odd hour on the strength of a guess.

Which channel the commitment lands on#

follow_up_channel reads the promise and routes it:

phone
A call-back. "I will ring you tomorrow", "someone will call you about the invoice" — the commitment is another call, and the phone follow-up drain is what places it.
task
Work for a person. "Send the quotation", "review the recording", "check with the warehouse" — a human does it, and the follow-up is the reminder that it was promised aloud.
Nothing at all
"No follow-up needed" schedules nothing. Not every call ends in a commitment, and inventing one so the record looks tidy would fill the queue with work nobody agreed to.

The distinction matters because the two are worked completely differently. A phone follow-up is executed automatically when it comes due, subject to its gates; a task follow-up waits for a person and sits in their queue until they close it.

What "NOT recorded" means#

Sometimes the tool answers the model with the words NOT recorded. That string is written for the model, not for a log: it is unambiguous, it cannot be read as a partial success, and it leaves the model no room to carry on the conversation as though a booking exists.

It appears when the promised time cannot be tied back to something the caller said or agreed to. The point is not to be strict about phrasing; it is that a voice which says "that is booked for Thursday" after inventing Thursday has told a customer something false, and the customer will find out on Thursday. The rules behind the refusal, and what the voice does next, are on the promise integrity page.

A refusal is visible afterwards too. A call where something was promised and nothing was booked produces the promised_unbooked finding on the quality review, so the gap shows up in the review rather than in a complaint.

What the language work did and did not touch#

Reconciled on 2026-09-10 against f5ea518, the commit that reworked language selection and regional style. It changed backend/app/voice_region.plan and nothing here: the time-word map in voice_worker/conversation still covers English, Telugu and Hindi, each in its own script and romanised, and it last moved in a different commit entirely. The words, the timezone, the channel routing and the fallback are unchanged.

What did change is worth knowing when you read a call back: the language a call settles into is now decided by tier — a remembered one is spoken from the first reply, a language merely made likely by the contact's city is not assumed but follows two or three words from the caller. A promise can therefore be made in a language the caller reached only part-way through, which is exactly why the matcher works on words in three languages rather than on the language the call opened in.

Questions#

The call-back was scheduled for 11:00 tomorrow and nobody said that. Why?

Because nothing in the promise parsed into a time, and that is the documented fallback. The follow-up still carries the words it came from, so you can correct the time before it runs. It is the one case where the due time is Connect's decision rather than the caller's.

Can a single call produce more than one follow-up?

Yes — a call-back on the phone channel and a piece of work on the task channel are separate commitments with separate due times, and a call that agreed to both creates both. Each is checked against what was actually said on its own.

Does a follow-up from a call look different from any other?

No. It is the same record with the same fields, worked by the same machinery, visible in the same queue. The origin is on it, which matters when somebody wants to hear how the promise was made — the transcript is one link away.