Skip to main content
ClaudeWave
Skill341 estrellas del repoactualizado today

phone-call

The phone-call skill enables outbound AI voice calls through Bland AI to complete tasks like booking reservations, scheduling appointments, or gathering information from businesses. Use it when you need an AI agent to conduct a live phone conversation, collect responses, and return a transcript and summary without manual dialing.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/Lilac-Labs/gini-agent /tmp/phone-call && cp -r /tmp/phone-call/skills/integrations/phone-call ~/.claude/skills/phone-call
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Phone Call

Place outbound phone calls through Bland AI. An AI voice agent dials the number, follows your task prompt in a live conversation, and the full transcript plus a summary come back when the call ends. Everything runs through `skill_run`:

```
skill_run({ skill: "phone-call", script: "place-call",
            args: { phoneNumber: "+15551234567", task: "..." } })
```

The runtime injects `BLAND_API_KEY` into the scripts — you never see or pass the key.

## Workflow

1. **Gather the full task.** Before anything else, collect: who to call (name + number), the goal, hard constraints (dates, times, party size, budget), fallbacks if the first ask isn't available, and the name to give if the callee asks who's calling. A vague task produces a bad call.
2. **Announce, then dial — the approval card is the confirmation.** In one short message, state who you're calling (the exact number) and what the agent will say or ask, then call `place-call` immediately. Do not ask "should I go ahead?" in chat: `place-call` always pauses on an Approve/Deny card, and approving that card is the user's go-ahead. A denied card ends the task; if the user sends a new message with changes, adjust per their feedback and submit a fresh `place-call` — never re-submit the identical call.
3. **Place the call** with `place-call`. It returns `{ ok, callId }`.
4. **Wait for the result** with `check-call`, passing `waitSeconds: 240` — the script polls Bland every 10 seconds internally and returns as soon as the call completes (or when the budget runs out). If the result comes back with `completed: false`, call `check-call` again with the same args and repeat until `completed` is `true`.
5. **Report back** the `summary` and the key points of the `transcript` (quote relevant exchanges, don't dump the whole thing unless asked). Optional: for structured answers about the call (did they confirm? what time?), run `analyze-call`.

If the user wants to abort a call in progress, run `stop-call` with the `callId`.

## Scripts

### place-call

```
skill_run({ skill: "phone-call", script: "place-call", args: {
  phoneNumber: "+15551234567",   // required, E.164
  task: "...",                   // required, the call prompt
  voice: "maya",                 // optional, Bland voice id/name
  firstSentence: "...",          // optional, exact opening line
  waitForGreeting: true,         // default true — wait for the callee to speak first
  record: false,                 // default false — see Rules
  maxDurationMinutes: 10,        // default 10
  language: "en-US"              // optional
} })
```

Returns `{ ok, callId }` or `{ ok: false, error }`.

### check-call

```
skill_run({ skill: "phone-call", script: "check-call", args: { callId: "...", waitSeconds: 240 } })
```

Returns `{ ok, callId, status, completed, answeredBy, callLengthMinutes, to, from, transcript, summary, recordingUrl, errorMessage }`. `waitSeconds` (optional, default 0, max 240) makes the script wait for the call to finish, polling Bland every 10 seconds; if the budget runs out first it returns the latest status with `completed: false` — call again with the same args. Fields Bland hasn't populated yet are omitted; `transcript` and `summary` appear only after `completed` is `true`. `callLengthMinutes` is in minutes. `answeredBy` distinguishes `human` from `voicemail`.

### stop-call

```
skill_run({ skill: "phone-call", script: "stop-call", args: { callId: "..." } })
```

Ends an in-progress call. Returns `{ ok, message }`.

### analyze-call

```
skill_run({ skill: "phone-call", script: "analyze-call", args: {
  callId: "...",                                      // required
  goal: "Book a dinner reservation",                  // optional context
  questions: [                                        // required, non-empty
    ["Did they confirm the reservation?", "boolean"],
    ["What time was booked?", "string"]
  ]
} })
```

Use after `check-call` reports `completed: true` when you need structured answers instead of reading the transcript — e.g. "Did they confirm the reservation?" → `true`. Each question is a `[question, answerType]` pair (`"string"`, `"boolean"`, `"number"`); a bare string question defaults to `"string"`. Returns `{ ok, answers }` with one answer per question, in order. Each analysis costs Bland credits, so prefer the transcript/summary for simple cases.

## Background watching

The workflow above is synchronous — right for short errand calls where the user is waiting on the result. When the user doesn't want to wait, or the call may run long, hand the waiting to a scheduled job with a `call-watch` pre-run hook: the hook polls Bland with zero model turns while the call is in progress, and wakes the job's turn exactly once, when the call finishes.

1. Place the call with `place-call` as usual and note the `callId`.
2. Create the watcher job:

```
create_job({
  name: "call-watch <callId>",
  intervalSeconds: 30,
  oneShot: false,        // must stay false — the silent in-progress ticks would auto-pause a one-shot job before the call finishes
  timeoutSeconds: 120,
  preRunHook: {
    handlerId: "skill-script",
    config: { skill: "phone-call", script: "call-watch", callId: "<callId>" }
  },
  prompt: "A phone call placed in the background has finished. The call result (status, summary, transcript) is in the fenced context items above — report the summary and the key transcript exchanges. Then find this job by name with list_jobs and delete_job it; the call is done and the watcher is no longer needed."
})
```

3. Tell the user the call is underway and the result will arrive in the job's chat thread, then end your turn — do not poll with `check-call`.

Notes:

- The report lands in the job's own chat thread (scheduled jobs deliberately do not post into the main chat).
- `call-watch` is the job's hook script, not for direct `skill_run` use. A failed call (never answered, rejected) also wakes the turn, so the user always hears the outcome.

##