Late Hold Triage
SkillAI & modelsLets your agent call a late guest, get their ETA, and decide whether to keep or release their held table.
Use Late Hold Triage in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Late Hold Triage and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the Late Hold Triage skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
About this skill
Places one outbound CALL-E call to a guest who is already late for a held table or appointment, captures a structured still-coming plus ETA result, and decides KEEP_HOLD, RELEASE_NOW, or NEEDS_HUMAN against the remaining hold window without calling the waitlist.
What this skill tells your AI
The instructions your AI receives, as published by calle-ai/awesome-phone-call-agents in skills/late-hold-triage/SKILL.md and read by Ahel’s review.
Use this skill when a booked guest is late right now and the floor needs a yes, a no, or a human — not a guess — before the held slot is given away.
late-hold-triage is a one-recipient decision skill. It does not add a CALL-E
backend queue, a campaign, or a waitlist dialer. It places at most one outbound
call to the late guest, reads a structured result, and compares the spoken ETA
to the hold that is still on the clock.
This is the missing half of next-day confirmation and first-accept cascades:
appointment-call-confirmcalls tomorrow's whole book in advancestandby/priority-call-waterfalloffer a freed slot down a list- this skill calls the late guest who still owns the slot and only then recommends whether a human should start a cascade
It never dials the waitlist. A RELEASE_NOW is a recommendation to the host,
not permission to ring the next person.
When To Use
Use this skill when:
- a restaurant, salon, clinic front desk, or repair shop is holding a slot for a guest who has passed the booked start time
- staff need a spoken ETA, not a text that may never arrive
- the hold has a hard end (
hold_until) and giving the slot away too early or too late both cost money - the operator asks something like "they're 12 minutes late — do we still hold table 7?"
When Not To Use
Do not use this skill to:
- confirm tomorrow's appointments — that is
appointment-call-confirm - fill a slot that is already free — that is
standbyorpriority-call-waterfall - call anyone other than the late guest on this run
- diagnose, treat, collect a debt, or discuss legal or medical substance
- infer a phone number, timezone, or hold end the operator did not supply
- treat silence, voicemail, or an unreadable answer as a release
Required Inputs
Ask for any of these that is missing. Do not infer one from locale, the phone number, or an earlier unrelated chat.
| Field | Notes |
|---|---|
guest_name | Spoken on the call so the right person can confirm identity |
phone | E.164, supplied by the operator |
slot_start | ISO 8601 with timezone — when the booking began |
hold_until | ISO 8601 with timezone — when the house stops holding |
business_name | Who the call says it is calling for |
context | One logistics sentence, e.g. "table for two at the window" |
Optional: region, locale, a dry-run fixture file, --now to replay a clock.
hold_until must be after slot_start. A hold that has already expired is
reported as HOLD_EXPIRED and no call is placed.
Core Workflow
- Collect the required fields. Refuse to invent a number or a hold end.
- Dry-run first. Print the masked destination, remaining hold minutes, and
the exact task text. Default mode places zero calls and needs no
install — see
scripts/triage_late_hold.py. - If the hold has already expired at
--now, stop. Do not call a guest about a slot the house has already given away. - Live mode requires both
--confirm(operator intent) and--authorized-numbers(this specific destination). Seereferences/safety.md. - Place exactly one CALL-E call with the shared
result_schemainreferences/result-schema.md. Poll it to a terminal state. - Decide with the deterministic rules in Runtime Workflow. Do not ask a second model to "interpret" the transcript.
- Report one of
KEEP_HOLD,RELEASE_NOW,NEEDS_HUMAN, orHOLD_EXPIRED, plus the masked phone andcall_id. If the decision isRELEASE_NOW, tell the operator they may now start a separate cascade skill. This skill will not start it.
Runtime Workflow
if now >= hold_until:
HOLD_EXPIRED # no call
else if spoken status is no_answer, voicemail, unclear, or missing:
NEEDS_HUMAN # never auto-release on silence
else if still_coming is false OR released is true:
RELEASE_NOW
else if still_coming is true AND eta_minutes is an integer:
if eta_minutes <= minutes_until(hold_until):
KEEP_HOLD
else:
RELEASE_NOW # they cannot arrive inside the hold
else:
NEEDS_HUMAN
eta_minutes must be a non-negative integer the guest actually spoke. A
vague "soon" or "on my way" without a number is NEEDS_HUMAN, not a keep.
An ambiguous CALL-E outcome (no call id, transport error, poll timeout) halts the run. It is not scored as a release.
Safety
Read references/safety.md. In short:
- Dry-run is the default. Live calls need
--confirmand an authorized number that exactly matches the guest phone. - One call, one destination, one attempt per run. No waitlist, no retry loop, no parallel legs.
- Phone numbers are masked in every printed or written summary.
- The API key is sent only to an allowlisted HTTPS CALL-E origin.
- Logistics only. The task text never asks about diagnosis, payment cards, or legal matters.
- CALL-E has no cancellation endpoint. Stopping the script prevents a call that has not been created; it cannot pull back a call already accepted.
Output
One decision row:
decision:KEEP_HOLD/RELEASE_NOW/NEEDS_HUMAN/HOLD_EXPIREDguest_name, masked phone,slot_start,hold_untilstill_coming,eta_minutes,releasedwhen the structured result has themcall_idwhen a live call was creatednext_step: empty on keep; "start a cascade skill if you want the slot filled" on release; "a human must read this call" on needs-human
Never claim a call completed unless CALL-E reached a terminal status.
Files
scripts/triage_late_hold.py— stdlib dry-run runner; live path needsrequestsfromrequirements.txtscripts/test_triage_late_hold.py— decision, gate, and masking testsassets/sample_holds.csv— fictional reserved-number fixturesassets/dry_run_outcomes.json— spoken outcomes for the dry-run clockassets/authorized_numbers.example.txt— format onlyreferences/result-schema.md— CALL-Eresult_schemaand task textreferences/safety.md— full safety contractreferences/examples.md— copy-paste dry-run and live commands
Signals
- GitHub stars
- 104
- Forks
- 528
- Last commit
- Sep 2026
Ahel review
K1binfo
installs-packages (in scripts/triage_late_hold.py)K1binfo
installs-packages (in references/examples.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
late-hold-triage- Source
- github.com/calle-ai/awesome-phone-call-agents
github.com/calle-ai/awesome-phone-call-agents
More in AI & models
Skill · anthropics
More in AI & modelstriage
Skill · mattpocock
More in AI & modelswayfinder
Skill · mattpocock
More in AI & modelsalgorithmic-art
Skill · anthropics
More in AI & modelscode-review-and-quality
Skill · addyosmani
More in AI & modelsmarketing-psychology
Skill · coreyhaines31
More in AI & models