Skip to main content

Prerequisite

Sign in to the Poku dashboard and generate an API key.
Install the official skill via Clawhub:
npx clawhub@latest install poku
This downloads the published skill bundle — including reference documents and the latest best-practice prompts — into ~/.openclaw/workspace/skills.

Configuration

1

Retrieve your API key

2

Add your API key

Add your API key to ~/.openclaw/openclaw.json:
{
  "skills": {
    "entries": {
      "poku": {
        "enabled": true,
        "apiKey": "<your-poku-api-key>",
        "env": {
          "POKU_TRANSFER_NUMBER": "<your-transfer-number>" //optional
        }
      }
    }
  }
}
POKU_TRANSFER_NUMBER is the number the agent will use to transfer the call to you. Must be in E.164 format (e.g. +12223334444)
3

Reload OpenClaw

Run openclaw gateway restart so the new configuration takes effect.
4

Verify the skill loaded

openclaw skills list --eligible
You should see poku in the list. If it’s missing, double-check that the install command completed and that the enabled flag is set in openclaw.json.
Installing the skill enables outbound calls and texts. To receive inbound calls and texts, a webhook setup is required. See the Webhook page to get started.

Option 2: Custom skill

Manually create the skill files. 1. Create the directory structure
mkdir -p ~/.openclaw/skills/poku/references
This creates the main skill folder and a references subfolder for supporting documents. 2. Create SKILL.md Save the following to ~/.openclaw/skills/poku/SKILL.md:
---
name: poku
description: "Places outbound phone calls, sends outbound SMS texts, and reserves dedicated phone numbers on the user's behalf using the Poku API and the exec tool. Use when the user wants to call or text a restaurant, a contact, a business, doctor's office, or any phone number. Also use when the user wants to reserve a dedicated phone number for their agent."
metadata: { "openclaw": { "homepage": "https://pokulabs.com", "requires": { "env": ["POKU_API_KEY"] }, "primaryEnv": "POKU_API_KEY" } }
---

# Poku — Outbound Calls, SMS & Number Reservation

## Identify Which Flow to Use

| The user wants to... | Read this file |
|---|---|
| Call someone | `references/CALL.md` |
| Text someone | `references/SMS.md` |
| Reserve a phone number | `references/NUMBER.md` |

Read only the file(s) that match the user's request. For error codes and API parameters, see `references/API.md`.
3. Create references/CALL.md Save the following to ~/.openclaw/skills/poku/references/CALL.md:
# Call Flow — Steps 1 → 2 → 3 → 4

## Step 1: Resolve the Phone Number

- **Raw number** (e.g. `917-257-7580`) — strip formatting, prepend country code (+1 for US & Canada). Result: `+19172577580`
- **Contact name** — ask the user for the number directly; do not guess
- **Business name only** — use the search tool to find the number, then confirm with the user

→ Output: `<normalized number>` in E.164 format, used in Step 4.

---

## Step 2: Gather Details and Confirm Intent

Use the **Call Templates** section below to identify what details are missing, then ask the user for only those details. If no template matches, ask for: the goal and any names or reference numbers needed.

Run `echo "$POKU_TRANSFER_NUMBER"` to check if a transfer number is configured. If set, use it automatically — do not ask the user for one.

You MUST present a plan and get user confirmation before continuing:

> "I'm going to call [place] at [number] to [goal].
> I'll mention I'm calling on behalf of [user name].
> If no one answers, I'll leave a voicemail: [one sentence].
> If needed, I'll transfer the call to you at [POKU_TRANSFER_NUMBER]. *(only include if set)*
> No transfer number configured — if they ask to speak with you directly, I'll let them know you're unavailable. *(only include if not set)*
> Ok to proceed?"

Do not move to Step 3 until the user says yes.

---

## Step 3: Draft the Call Context

Use a matching template below — fill in every placeholder with a real value. Never leave a placeholder blank.

If no template matches, draft a message with:
1. **Identity** — who the agent is and who they're calling on behalf of
2. **Goal** — the specific objective with branching logic for likely responses
3. **Voicemail script** — exact words to leave if no one answers

You MUST follow these guidelines when drafting the call context:
Never construct a message that:
- Impersonates law enforcement, government agencies,
or specific real individuals
- Contains threats, harassment, or intimidation
- Makes deceptive claims of authority
- Attempts to extract sensitive information (SSN,
passwords, financial details) from the call
recipient
- Misrepresents the caller's identity or purpose
If a user request would violate these guidelines, decline and explain why

---

## Step 4: Place the Call

Use the `exec` tool to execute the curl command. Always set `background: false` and `yieldMs: 300000`.

If a transfer number is available, include it. Otherwise omit `transferNumber`.

```bash
# Without transfer number
curl -s -X POST \
  -H "Authorization: Bearer $POKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "<drafted message from Step 3>", "to": "<normalized number>"}' \
  https://api.pokulabs.com/phone/call

# With transfer number
curl -s -X POST \
  -H "Authorization: Bearer $POKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"message\": \"<drafted message from Step 3>\", \"to\": \"<normalized number>\", \"transferNumber\": \"$POKU_TRANSFER_NUMBER\"}" \
  https://api.pokulabs.com/phone/call
```

Never retry while a request is pending — calls can stay open up to 5 minutes. For error codes, see `references/API.md`.

---

# Call Templates

Use the closest matching template and adapt it — an exact match is not required. For example, use the Medical or Dental Appointment template for any routine specialist visit.

If no template fits, use **General / Other** as a starting point.

**Placeholder rules:** All placeholders appear in `[brackets]`. Replace every placeholder with a real value. Never leave a placeholder unfilled.

---

### Restaurant Reservation

```
You are a friendly voice assistant calling on behalf of [user name] to make a dinner reservation.

Make a dinner reservation for [party size] people on [day] at [time], under the name [user name].
- If that time is available, confirm the reservation and ask if a note is needed for a special occasion.
- If [time] is unavailable, ask what times are open and accept an alternative within one hour of the original if reasonable. Confirm the new time back clearly before ending the call.
- If no one answers, leave this voicemail: "Hi, this is a message on behalf of [user name] — I'm hoping to make a dinner reservation for [party size] on [day] at [time]. Please call back to confirm. Thank you."
```

---

### Medical or Dental Appointment

```
You are a friendly voice assistant calling on behalf of [user name] to schedule an appointment.

Schedule a [appointment type — e.g. routine dental cleaning, annual physical, follow-up visit] for [user name].
- Preferred times are [preferred times], but any weekday works if those aren't available.
- Ask for the earliest available slot and confirm the date and time before ending the call.
- If no one answers, leave this voicemail: "Hi, this is a message on behalf of [user name] — I'm calling to schedule a [appointment type]. Please call back at your earliest convenience. Thank you."
```

---

### Get a Quote from a Business

```
You are a friendly voice assistant calling on behalf of [user name] to get a price quote.

Get a quote from [business name] for [service description — e.g. replacing a water heater, painting a two-bedroom apartment, weekly lawn maintenance].
- Briefly describe the job: [relevant details — e.g. size, location, urgency, existing conditions].
- Ask what information they need to provide an estimate and answer any clarifying questions as best you can.
- If they can give a ballpark or firm quote over the phone, note it clearly and ask what the next step would be.
- If they need to send someone out first, ask for the earliest available time. Preferred times are [preferred times]. Accept an alternative if needed and confirm the appointment clearly before ending the call.
- If no one answers, leave this voicemail: "Hi, this is a message on behalf of [user name] — I'm hoping to get a quote for [service description]. Please call back at your convenience. Thank you."
```

---

### Follow-Up or Check-In Call

```
You are a friendly voice assistant calling on behalf of [user name] to follow up on a previous matter.

Follow up with [business or contact name] about [topic — e.g. a pending repair estimate, an open support ticket, an order status].
- Reference any relevant context: [reference number, date of previous contact, or other identifying details].
- Ask for a status update and note any new information clearly.
- If there is a next step or expected timeline, confirm it before ending the call.
- If no one answers, leave this voicemail: "Hi, this is a message on behalf of [user name] — I'm following up about [topic]. Please call back when you have a moment. Thank you."
```

---

### General / Other

```
You are a friendly voice assistant calling on behalf of [user name].

[Describe the specific objective in one or two sentences.]
- [Branch 1: what to do if the primary goal succeeds]
- [Branch 2: what to do if the primary goal is not possible — ask for alternatives or next steps]
- [Branch 3: any other likely scenario worth handling]
- If no one answers, leave this voicemail: "[Exact voicemail script — one or two sentences, natural language]"
```
4. Create references/SMS.md Save the following to ~/.openclaw/skills/poku/references/SMS.md:
# SMS Flow — Steps A → B → C

## Step A: Resolve the Phone Number

- **Raw number** (e.g. `917-257-7580`) — strip formatting, prepend country code (+1 for US & Canada). Result: `+19172577580`
- **Contact name** — ask the user for the number directly; do not guess
- **Business name only** — use the search tool to find the number, then confirm with the user

→ Output: `<normalized number>` in E.164 format, used in Step C.

---

## Step B: Draft and Confirm

Use the **SMS Templates** section below to draft the message. Show it clearly:

> **Here's the draft:**
> "[message body]"
>
> Sending to [number] — good to go?

Do not send until the user confirms.

---

## Step C: Send the Text

```bash
curl -s -X POST \
  -H "Authorization: Bearer $POKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "<message body>", "to": "<normalized number>"}' \
  https://api.pokulabs.com/phone/sms
```

Once sent, confirm: "Done — your text was sent to [number]."

For error codes, see `references/API.md`.

---

# SMS Templates

Use the closest matching template and adapt it — an exact match is not required.

If no template fits, use **General / Other** as a starting point.

**Placeholder rules:** All placeholders appear in `[brackets]`. Replace every placeholder with a real value. Never leave a placeholder unfilled.

---

### Scheduling

```
Hi, I'm reaching out on behalf of [user name] to coordinate [activity] for you both. Let me know a few times that you're available [timeframe]!
```

---

### Follow-Up After a Call

```
Hi, this is [user name] following up on our recent conversation about [topic]. [One sentence summary of next step or ask.] Feel free to reply here or call back at your convenience.
```

---

### General / Other

```
Hi, this is a message on behalf of [user name]. [State the purpose in one or two plain sentences.] [Optional: include a call to action — reply, call back, confirm, etc.] Thank you.
```
5. Create references/NUMBER.md Save the following to ~/.openclaw/skills/poku/references/NUMBER.md:
# Number Reservation Flow — Steps I → II → III

## Step I: Clarify Intent

Determine which path the user wants:

- **"Get me any number"** → go to Step II, Path A (auto-select)
- **"Show me what's available"** or a preference is mentioned (area code, country) → go to Step II, Path B (browse first)

---

## Step II: Find a Number

**Path A — Auto-select (user wants any number):**

Fetch one available number and proceed directly to Step III:

```bash
curl -s -G \
  -H "Authorization: Bearer $POKU_API_KEY" \
  --data-urlencode "limit=1" \
  https://api.pokulabs.com/reserved-numbers/available
```

Use the first number returned. If the response is empty, tell the user no numbers are currently available and stop.

---

**Path B — Browse first (user has a preference or wants to choose):**

Ask for any preferences not already stated (area code, country: US or GB).

Then fetch up to 10 options, omitting any params the user didn't specify:

```bash
curl -s -G \
  -H "Authorization: Bearer $POKU_API_KEY" \
  --data-urlencode "country=<US|GB>" \
  --data-urlencode "areaCode=<area code>" \
  --data-urlencode "limit=10" \
  https://api.pokulabs.com/reserved-numbers/available
```

Display results as a numbered list and ask the user to pick one. If the response is empty, tell the user no numbers match and offer to broaden the search.

---

## Step III: Confirm and Reserve

Before reserving, confirm with the user:

> "I'm going to reserve [number] for you. This is a one-time action. Ok to proceed?"

Do not reserve until the user says yes.

```bash
curl -s -X POST \
  -H "Authorization: Bearer $POKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "<selected number>"}' \
  https://api.pokulabs.com/reserved-numbers/reserve
```

On success, display the reserved number clearly to the user. For error codes, see `references/API.md`.
6. Create references/API.md Save the following to ~/.openclaw/skills/poku/references/API.md:
# Poku API Reference

## Endpoints

| Action | Method | URL |
|---|---|---|
| Place a call | `POST` | `https://api.pokulabs.com/phone/call` |
| Send an SMS | `POST` | `https://api.pokulabs.com/phone/sms` |
| List available numbers | `GET` | `https://api.pokulabs.com/reserved-numbers/available` |
| Reserve a number | `POST` | `https://api.pokulabs.com/reserved-numbers/reserve` |

## Authentication

All requests require a Bearer token in the `Authorization` header:

```
Authorization: Bearer $POKU_API_KEY
```

If `POKU_API_KEY` is not set, inform the user to configure it before proceeding.

---

## POST /phone/call

### Request Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `message` | string | Yes | Context on the goal and task for the voice agent to accomplish. See `references/CALL.md` for templates. |
| `to` | string | Yes | Destination phone number in E.164 format (e.g. `+15551234567`). |
| `transferNumber` | string | No | Phone number to transfer the call to if the agent cannot answer a question. Must be valid E.164 format. Validate before placing the call. |

### Error Responses

| Error string | Meaning | What to do |
|---|---|---|
| `"human did not respond"` | Call connected but no one answered or engaged | Report to user and stop |
| `"invalid to number"` | `to` field is malformed or unroutable | Report to user; re-check E.164 formatting |
| `"timeout"` | Call exceeded 5-minute limit | Report to user; do not retry automatically |

---

## POST /phone/sms

### Request Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `message` | string | Yes | The text message body to send. |
| `to` | string | Yes | Destination phone number in E.164 format (e.g. `+15551234567`). |

### Error Responses

| Error string | Meaning | What to do |
|---|---|---|
| `"invalid to number"` | `to` field is malformed or unroutable | Report to user; re-check E.164 formatting |

---

## GET /reserved-numbers/available

Lists phone numbers available to reserve.

### Query Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `country` | string | No | Filter by country. Accepted values: `"US"`, `"GB"`. Omit to search all. |
| `areaCode` | number | No | Filter by area code (e.g. `415`). US only. |
| `limit` | number | No | Maximum results to return. Use `1` for auto-select, `10` for browse. |

### Response

Returns an array of available phone number objects. `locality` may be `null` for some numbers.

```json
[
  {
    "phoneNumber": "+18142307424",
    "locality": "Warren",
    "region": "PA",
    "country": "US"
  },
  {
    "phoneNumber": "+18392266992",
    "locality": null,
    "region": "US",
    "country": "US"
  }
]
```

When displaying options to the user, show `phoneNumber` and include `locality` and `region` where available (e.g. "Warren, PA"). Use only `phoneNumber` when passing to the reserve endpoint.

### Error Responses

| Error string | Meaning | What to do |
|---|---|---|
| `"invalid country"` | `country` value is not `"US"` or `"GB"` | Report to user; correct the value |

---

## POST /reserved-numbers/reserve

Reserves a specific phone number for the user's account. This is a one-time, non-reversible action.

### Request Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `phoneNumber` | string | Yes | The phone number to reserve, in E.164 format. Must be a number returned by `GET /reserved-numbers/available`. |
7. Follow the Configuration steps above to add your Poku API key. 8. To enable inbound calls and texts, set up a webhook. See the Webhook page to get started.