Executing a follow-up
runner.chase_phone drains phone rows every tick, two at a time, through voice_engine.place_call — the same gates as any outbound call rather than a shortcut past them. Each attempt is written back as call placed <id>, awaiting approval <id> or refused: <reason>. A line that is not ready is retried in an hour.
The drain, and why it is deliberately slow#
Draining runs on the engine's tick and takes two rows per tick on the phone channel. That rate is a choice, not a limit somebody forgot to raise. Ten call-backs falling due at nine in the morning should become ten calls spread over several ticks, not ten lines seized at once — which would exhaust capacity, look like a dialler to the people being rung, and make a single bad batch unrecoverable.
It also means "due" is a permission rather than an appointment. A row becomes eligible at its due time and is acted on at the next pass that reaches it. A minute or two between the two is normal and is not a fault to investigate.
The gates, none of which the follow-up skips#
| Gate | What it checks | What happens when it stops the row |
|---|---|---|
| Autonomy | Whether this channel may act without asking | Recorded as awaiting approval <id> and put in front of a person |
| Suppression and do-not-contact | Whether this person may be contacted at all | Recorded as a refusal; approving is not one of the answers |
| Line readiness | Whether a usable line exists right now | Retried in an hour — the row is not lost and not burned |
| Allowance and budget | What the workspace's plan permits | Recorded as a refusal with the reason; it clears when the allowance does |
| Lateness | Whether the row is more than 24 hours past due | Closed as missed: and never rung |
The phrase that matters is *the same gates as any outbound call*. There is no privileged path for scheduled work: a follow-up cannot ring somebody who has asked not to be rung, cannot spend an allowance that is gone, and cannot bypass an approval rule because the commitment was made yesterday. A scheduled action is still an action.
What is written back#
call placed <id>- The call went out and carries an identifier. From there it is an ordinary call with its own transcript, summary and cost — the follow-up's job is finished at the point of placing it.
awaiting approval <id>- The attempt is held. Nothing has been dialled, the person has not been contacted, and the row is waiting on a decision in Needs You.
refused: <reason>- A gate stopped it and named itself. The reason is the actionable part: some refusals clear on their own, some need a person, and some are the correct permanent answer.
- Nothing new on the row
- No tick has reached it yet, or it is not due. Check the due time before looking for a fault.
The other channels#
A message channel drains the same way in shape: the row comes due, the drain composes and attempts the action, and the channel's ordinary boundary decides whether it leaves. The differences are in what the gates are — a mailbox's health and daily allowance rather than a line's readiness — and in what success means, which for a message is the provider's own acknowledgement rather than a call identifier.
task is the exception with no drain at all. Nothing picks a task row up, at any tick, ever. If you are waiting for one to execute, the wait is the whole problem — see Follow-ups for a person to do.
Questions#
Why did two call-backs go out and the other six did not?
Two rows per tick on the phone channel. The other six are still queued and will be taken on following ticks, in order, unless a gate or the twenty-four-hour rule reaches them first.
Does a refused attempt count against the commitment?
No. The row stays open and still owed; the refusal is recorded against it with its reason. What a refusal changes is who needs to act next — usually you, and usually on the gate rather than on the row.
Can I run the drain manually for one row?
The queue is worked by the engine on its tick rather than triggered per row. If a commitment needs keeping right now, keep it — ring the person, send the message — and complete the row, which is faster than waiting for a scheduler in any case.