calle-ai/awesome-phone-call-agents/afterhold-ivr-errand
Claude Code and agent skill by calle-ai/awesome-phone-call-agents
- community
Checking that the SKILL.md file is still in the repository.
Run one outbound CALL-E call (mock by default, live only with explicit confirmation) on behalf of a user, capture the conversation, and return a structured brief. AfterHold owns the safety layer, the workspace, and the mission state machine; CALL-E owns the call and the conversation runtime. This skill is a portable workflow: given an authorized E.164 number, a natural-language goal, a language, a schedule, and a result schema, build a CALL-E task, run it (or dry-run), poll status, and persist the brief.
Install
npx vskill@latest install calle-ai/awesome-phone-call-agents/afterhold-ivr-errandSKILL.md
afterhold-ivr-errand
AfterHold is a workspace + safety layer in front of the CALL-E call runtime. You (the assistant using this skill) send one outbound call per "mission", poll until terminal, and write a structured brief. You do not hold CALL-E keys — the AfterHold API does. You talk to AFTERHOLD_API_BASE over HTTPS with a JWT bearer token.
When to use
Use this skill when the user wants to delegate a phone task to CALL-E without making the call themselves. Examples:
- "Call BlueDart and ask if AWB 8821 is out for delivery."
- "Reschedule my 4:30 PM appointment at Dr. Mehta's clinic to tomorrow."
- "Confirm a 7:30 PM table for two at Pizza Hut Bandra."
- "Check the status of my electricity outage ticket."
Do not use this skill for:
- Anything requiring payments, money movement, or account cancellation (refused by policy).
- Medical advice or clinical interpretation (refused by policy).
- Legal advice or legal-record destruction (refused by policy).
- Mass/batch calls (v1 is one recipient per mission).
Inputs
The user (or another tool) supplies:
| Field | Type | Required | Notes | |||||
|---|---|---|---|---|---|---|---|---|
e164 | string (E.164) | yes | Destination phone. Must be on the user's allowlist. | |||||
display_name | string | yes | Human label, e.g. "BlueDart Chennai Hub". | |||||
goal | string | yes | Natural-language description of what to achieve. | |||||
language | BCP-47 | no | Default en-IN. | |||||
archetype | enum | no | courier \ | clinic \ | restaurant \ | utility \ | general. Default general. | |
schedule_at | ISO ms | no | Default null (call now). If set, the server will start when due. | |||||
extract_schema | JSON Schema | no | Default canonical envelope (see references/result-schema.md). |
Outputs
The skill returns a Brief:
If the call did not reach a human (voicemail / unavailable / refused / failed), the brief still returns — do not retry without surfacing the failure to the user.
Side effects
- One outbound CALL-E call. In the default mock mode no call is placed. A mission with a future
schedule_at is stored as scheduled and dialed by the server at that time, not now.
- The destination receives a phone call from CALL-E's voice runtime on behalf of the user.
- The AfterHold server stores the mission, all events, and the resulting brief.
- The CALL-E free tier is 20 calls per new account. The server enforces a 5-call-per-hour rate limit per user.
Cancellation
The user can cancel a mission:
What cancel does, and does not do:
- A mission that has not been sent to CALL-E yet (
draft,previewed,scheduled) is canceled and
will never be dialed.
- A mission whose call CALL-E has already accepted is marked
canceledlocally and AfterHold stops
tracking it. This does not recall the call. It may still ring, connect and complete. The response says call_recalled: false. Use the CALL-E dashboard if you need to stop an in-flight call.
- A mission in
submission_unknownis canceled locally the same way; check the CALL-E dashboard to see
whether the call exists.
Credentials
AfterHold API requires:
AFTERHOLD_API_BASE— base URL. Defaults tohttp://127.0.0.1:8787. A non-local server must be
https and must also be approved with AFTERHOLD_ALLOW_ORIGIN=<same origin>. Credentials are never sent to any other origin and redirects are refused.
AFTERHOLD_JWT— bearer token. Get one by callingPOST /v1/auth/loginwith the user's email + password.CALLE_API_KEYis never used by callers. It lives only on the AfterHold server, which only sends
it to https://api.heycall-e.com or https://test-api.heycall-e.com.
If AFTERHOLD_API_BASE or AFTERHOLD_JWT is missing, stop and tell the user rather than guessing.
Dry-run (the default)
The server runs in mock mode by default (CALLE_MOCK=1). The mock adapter walks the same phase timeline (queued → planning → dialing → in_conversation → wrapping → completed) with a believable transcript and a courier-style brief. No call is placed and no CALL-E key is needed. All sample numbers are fictional 555-01xx numbers.
dry-run.mjs only talks to a loopback server and exits before sending anything if /health does not report mock: true. See references/server.md.
Workflow
Step 1 — Create a draft mission
→ returns a mission with status: "draft". Save id and idempotency_key (the server already dedupes).
Step 2 — Preview (auto-generates the task string)
→ returns task_string (read it back to the user before live), extract_schema, status previewed. The task string is rendered from a deterministic template; see references/task-template.md.
Step 3 — Start (gates + create the call)
Gates the server runs:
- Live mode only: the request body must be
{"confirm_live": true}and the mission must have a
region (ISO 3166-1 alpha-2, never inferred). Otherwise 400.
CALLE_ENABLEDenv is1. If0, return503.- User has granted explicit consent. If not, return
412. e164is on the user's allowlist (skipped underCALLE_MOCK=1). Otherwise403.- The actual dial time is outside quiet hours. Otherwise
429. - Rate limit: ≤5 starts per user per hour. Otherwise
429.
Scheduling. schedule_at must be in the future (past values are 400) and is checked against quiet hours at that time. Starting such a mission stores it as scheduled; it is not dialed now. The server's sweeper dials it when due and re-runs every gate at that moment, so a schedule cannot be used to get around quiet hours, a revoked consent, or the kill switch.
If all gates pass, the server atomically claims the mission and creates the call via CALL-E (POST /v1/calls), then a background worker polls GET /v1/calls/{id} every POLL_INTERVAL_SEC (8s by default; 1.5s under CALLE_MOCK=1). First poll waits POLL_FIRST_DELAY_SEC (60s live, 0 mock).
Unknown creation. If the create request times out, drops, or returns 5xx, the call may exist. The mission becomes submission_unknown: it is never auto-retried or replaced, and /retry returns 409 until you check the CALL-E dashboard and reconcile it.
Step 4 — Stream events
Use this for an on-screen "neural stream" (transcript, phase, transcript excerpts). The server appends one event per status change and one per callee transcript line. The iOS client polls this every 1.5s while the Live Call screen is open.
Step 5 — Read the brief
When the mission reaches a terminal state, GET /v1/missions/{id} returns brief:
Failure mapping (server §17)
| CALL-E / telco | Mission status | Brief outcome | |
|---|---|---|---|
| Completed + schema filled | completed | resolved or needs_human (from JSON) | |
| Voicemail detected | voicemail | voicemail | |
| No answer / busy | failed | unavailable | |
| User cancel | canceled | — | |
| API 4xx on create | failed | failed | |
| Create timed out / 5xx (call may exist) | submission_unknown | — (reconcile first) | |
| Ambiguous transcript | completed | needs_human (do not invent facts) |
Phone-like numbers are masked (last 4 digits kept) in every response body: goals, task strings, events, briefs and errors. The destination is always returned as a redacted E.164.
Evidence quote strings must be spans from the actual transcript. If you cannot point at a span, leave the fact empty — do not hallucinate.
Example task strings
See examples/ for full worked examples:
courier.json— BlueDart package trackingclinic.json— appointment reschedulerestaurant.json— table confirmationutility.json— outage status
Example archetype choices
| If the user says… | Use archetype | |
|---|---|---|
| "track my package", "delivery status", "where's my order" | courier | |
| "reschedule appointment", "doctor booking", "clinic visit" | clinic | |
| "book a table", "restaurant reservation", "confirm order" | restaurant | |
| "power outage", "gas leak", "water bill", "phone bill" | utility | |
| Anything else | general |
Local development
Live mode
Live mode is opt-in, for operators who control the recipients. It is a hackathon-grade demo path, not a production platform.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/afterhold-ivr-errand/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/calle-ai/awesome-phone-call-agents/afterhold-ivr-errand)