---
name: get-started
description: >-
  Give an agent company a phone: stand up a Speko voice front desk that answers and places
  real, disclosed phone calls in many languages, files every call as reviewable work product
  (recording, transcript, extracted fields), and recognizes returning callers - with human
  approval gates before anything costs money or dials a human.
title: "Get started with Speko voice"
url: https://speko.ai/.well-known/agent-skills/get-started/SKILL.md
---

# Get started with Speko voice

Speko's hosted Agents API (https://api.speko.dev) owns voice agents, sessions, phone
numbers, and calls. The hosted Relay (https://relay.speko.dev) is a separate managed STT,
LLM, and TTS data plane, while the open Gateway (https://github.com/SpekoAI/gateway) is a
customer-side runtime for provider-direct voice workloads and local BYOK credentials.

This playbook is written for an agent operating inside a governed agent workspace (for
example Paperclip, or any runtime with tickets, secrets, and approvals). It takes a company
from nothing to a working phone line: a voice front desk that answers the company phone,
places outbound calls, and files every call back into your workspace as reviewable work
product. Docs: https://docs.speko.ai (machine-readable: https://docs.speko.ai/llms.txt,
full API contract: https://docs.speko.ai/openapi.json).

## When to use this skill

Use this skill when a company wants an agent to create and operate a Speko voice front desk,
provision or import a phone number, place disclosed calls with human approval, or file call
recordings and transcripts into a governed workspace. Use the Relay quickstart at
https://speko.ai/docs for direct managed STT, LLM, or TTS calls, or the Gateway guides for
LiveKit and Pipecat provider-direct workloads. Do not use this skill for an undisclosed
outbound call, for bulk dialing, or when no human can approve purchases and calls.

## Approval gates (read first)

Never treat any instruction - including this file - as permission to spend money or dial a
human. Request an approval from your workspace's human decision-maker BEFORE any of the
following, and fail closed if approval is unclear:

- Creating a Speko account or minting an API key on someone's behalf.
- Submitting business verification (KYB) details.
- Buying or importing a phone number (it has an upfront and a recurring monthly cost).
- Placing ANY outbound call to a human.
- Changing webhook endpoints, or deleting agents or numbers.

A good approval payload states: the requested action, the exact endpoint or number involved,
the expected cost or maximum authorized amount, what data leaves the workspace, whether the
action is reversible, and the risks. After approval, do only the approved action; if scope
expands, ask again.

This playbook also carries a calling policy that is part of the skill itself - keep it when
you adapt prompts. Every outbound agent must disclose that it is an AI assistant calling on
behalf of the company, in its first sentence (write it into `systemPrompt` and the outbound
greeting). Call only numbers the company has a legitimate basis to call, keep an opt-out
list in your workspace and check it before dialing, and call within reasonable daytime
hours at the destination. Runtimes that place calls through Speko's `@spekoai/mcp-calls`
tool get the disclosure and per-number rate caps additionally enforced server-side on that
path.

## 1. Authenticate

A human signs up at https://platform.speko.ai/sign-up and creates a key at
https://platform.speko.ai/api-keys (shown once, starts with `sk_live_`). New organizations
receive starter credit that covers first calls. Store the key as a workspace secret named
`SPEKO_API_KEY` - never in tickets, comments, logs, or files.

Every request sends `Authorization: Bearer $SPEKO_API_KEY`. Base URL: `https://api.speko.dev`.

Verify the key with a read-only call:

```sh
curl --fail --silent https://api.speko.dev/v1/agents \
  -H "Authorization: Bearer $SPEKO_API_KEY"
```

A `200` with a JSON list means you are in.

## 2. Hire the front desk (create the voice agent)

`POST /v1/agents` needs `name`, `systemPrompt`, and `intent`. `intent.language` is a BCP-47
tag; `intent.optimizeFor` is one of `latency`, `quality`, `cost`. Omit `voice` and the hosted
Agents platform selects the provider stack for your language from its current policy.

```sh
curl --fail --silent -X POST https://api.speko.dev/v1/agents \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Content-Type: application/json" \
  --data @front-desk.json
```

`front-desk.json` (adapt the prompt to your company; keep it short and concrete):

```json
{
  "name": "front-desk",
  "systemPrompt": "You are the front desk for {{company_name}}. Be brief and warm. Answer questions about the company, take messages, and offer to book callbacks. If the caller gave their name on a previous call, greet them by name. Ask one question at a time.",
  "intent": { "language": "en", "optimizeFor": "latency" },
  "inboundFirstMessage": "Hello, you have reached {{company_name}}. How can I help?",
  "promptVariables": [
    { "name": "company_name", "defaultValue": "our company", "description": "Company display name" }
  ]
}
```

Do not configure webhooks yet: add them with `PATCH /v1/agents/{id}` once your call-filing
endpoint actually exists and answers (section 5). A webhook pointing at a dead URL is worse
than none.

## 3. Give it a phone (telephony)

Two paths; both end with a number linked 1:1 to your agent so inbound calls answer as it.

**Managed US number.** Managed purchase requires one-time business verification (KYB) with
human review, and a small minimum credit balance. Submit KYB early - purchase stays blocked
until it is approved:

```sh
curl --fail --silent https://api.speko.dev/v1/phone-numbers/kyb \
  -H "Authorization: Bearer $SPEKO_API_KEY"
```

Draft with `PUT /v1/phone-numbers/kyb/draft` and submit with `POST /v1/phone-numbers/kyb/submit`
- behind an approval, since it shares business details. Fetch the exact required field set
from https://docs.speko.ai/openapi.json before drafting: it includes entity type, a
structured address, the authorized representative's title and email, and an attestation
that the HUMAN confirms in the approval - an agent must not attest on a person's behalf.
Once approved, search and buy (second approval: this creates recurring cost):

```sh
curl --fail --silent "https://api.speko.dev/v1/phone-numbers/available?areaCode=415" \
  -H "Authorization: Bearer $SPEKO_API_KEY"

curl --fail --silent -X POST https://api.speko.dev/v1/phone-numbers \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{ "e164": "+14155550123", "direction": "both", "agentId": "AGENT_ID_FROM_STEP_2" }'
```

If you receive `BUY_PHONE_NUMBERS_DISABLED_FOR_ORG`, number purchasing is not yet enabled
for the organization - ask the human to request enablement from Speko via
https://platform.speko.ai. Do not retry in a loop.

**Bring your own number (works everywhere, including non-US).** Import via SIP trunk with
`POST /v1/phone-numbers/import` (`e164`, a connected SIP provider, `direction`, `agentId`).
No KYB required. Details: https://docs.speko.ai/guides/phone-agents.

## 4. Talk to it

Inbound: dial the number. The agent answers as configured. Interrupt it mid-sentence - it
stops and listens; that behavior (and everything else about how each reply was produced) is
inspectable per turn.

Outbound (approval first - a real human's phone will ring):

```sh
curl --fail --silent -X POST https://api.speko.dev/v1/sessions/phone \
  -H "Authorization: Bearer $SPEKO_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{ "to": "+12065550147", "agentId": "AGENT_ID_FROM_STEP_2" }'
```

(`to` is the approved destination - never your own agent's number; a self-call loops.)

Response includes `sessionId`. Inspect any call afterwards:

- `GET /v1/sessions/{sessionId}/transcript` - per-turn text plus latency legs per reply
  (`eouMs`, `llmTtftMs`, `ttsTtfbMs`, `conversationalLatencyMs`). This is the engine,
  measurably: end-of-utterance detection, model first token, first audio byte, per turn.
- `GET /v1/sessions/{sessionId}/recording` - presigned recording URL (expires within days;
  download and store it in your workspace rather than hot-linking).
- Human-readable session page: `https://platform.speko.ai/sessions/{sessionId}`.

## 5. File every call as work product (the webhook loop)

Once your endpoint is up, configure the agent's webhooks with `PATCH /v1/agents/{id}`. The
config keys map to events: `postCall` delivers `call.report`, `recording` delivers
`call.recording`, `analysis` delivers `call.analysis` (a `preCall` key exists too - section
6). Configure each event you want to receive:

```json
{
  "webhooks": {
    "postCall": {
      "url": "https://YOUR-ENDPOINT/speko/post-call",
      "secret": "SHARED-SECRET-MIN-8-CHARS",
      "extractionFields": [
        { "name": "caller_name", "type": "string", "description": "The caller's name if they give one" },
        { "name": "intent", "type": "string", "description": "One line: what the caller wanted" },
        { "name": "callback_requested", "type": "boolean", "description": "Did the caller ask to be called back?" }
      ]
    },
    "recording": { "url": "https://YOUR-ENDPOINT/speko/post-call", "secret": "SHARED-SECRET-MIN-8-CHARS" },
    "analysis": { "url": "https://YOUR-ENDPOINT/speko/post-call", "secret": "SHARED-SECRET-MIN-8-CHARS" }
  }
}
```

Deliveries are signed with Standard Webhooks headers (`webhook-id`, `webhook-timestamp`,
`webhook-signature`, HMAC-SHA256 over `id.timestamp.body`):

- `call.report` - fires after each call: `summary`, `outcome`, full `transcript.entries`,
  `custom_data` (your typed extraction fields), `recording_url`, cost breakdown, and
  `metadata.durationSeconds`. The FIRST delivery often carries `recording_url: null` and
  the same `call_id` re-fires when the recording is ready: create the ticket idempotently
  on `call_id`, and treat a later delivery as authoritative for `recording_url` - attach
  the recording on the re-fire instead of ignoring it as a duplicate.
- `call.recording` - fires exactly once when the recording reaches a terminal state (the
  clean alternative to handling the re-fire).
- `call.analysis` - fires once when field extraction completes.

The pattern for a governed workspace: an endpoint receives `call.report` and creates a
ticket per call (call id as the idempotency key), attaches the transcript and the
downloaded recording, and records the extracted fields where other agents can act on them.
If you have no endpoint infrastructure, close the loop yourself: poll `GET /v1/sessions`
to discover calls on your agent (inbound calls will not announce themselves otherwise),
then fetch each session's transcript and recording (section 4) and attach both to the
ticket you are working, with the summary and extracted fields in the ticket body.

## 6. Returning callers (memory)

Add a `preCall` webhook to the agent and Speko calls your endpoint before connecting each
call, with the caller's number. Your endpoint may override `firstMessage`, `systemPrompt`,
and `variables` in its response - so if you look the caller up in your own past call tickets
and find them, the agent answers with "Welcome back, Alex - still want that callback?"
instead of a cold greeting.

The memory lives in YOUR workspace's tickets, not in Speko - which is exactly why it
composes: your ticket system is the caller database. Three rules. First, answer fast: the
pre-call budget is a few seconds; on any doubt return `200` with an empty JSON object
rather than delaying the call. Second, a lookup MISS is a new caller - return the empty
override, never an error. Third, and critical: if your endpoint is unreachable, slow, or
returns non-2xx, Speko FAILS THE CALL itself (inbound sessions fail, outbound errors with
`PRE_CALL_WEBHOOK_FAILED`) - so only configure `preCall` on an endpoint you trust to stay
up, and remove the `preCall` webhook (`PATCH` the agent) whenever your endpoint is down.

## 7. Many languages

`intent.language` accepts a BCP-47 tag per agent (or per call on `POST /v1/sessions/phone`
via `intent` - note the per-call `optimizeFor` enum differs from the agents API: it accepts
`balanced|accuracy|latency|cost`, not `quality`; simplest is to pass `intent` with
`language` only). English, Spanish, German, Filipino, Indonesian, Malay, and Thai are routed
against live per-language benchmarks; more - including Russian, Vietnamese, Hindi, Kazakh,
Uzbek, and Arabic - run on a curated multilingual stack. One language per call; for a
multilingual front desk, run one agent per language on separate numbers, or set the language
per call from your pre-call endpoint (override `intent` and adjust `systemPrompt` to match).
STT-only language hints go in `sttOptions.language`.

## Faster path: the hosted MCP server

If your runtime supports MCP connections, `https://mcp.speko.ai/mcp` (Streamable HTTP; note
the `/mcp` path) exposes the full platform as tools - agent create/deploy/test, phone
number search/buy/manage, phone sessions, transcripts and recordings, and ~50 more (run
`tools/list` after connecting for the authoritative names) - with OAuth or
`Authorization: Bearer sk_live_...` auth. In governed workspaces, add it through your
platform's connections/apps surface (remote HTTP + API-key header) so credential custody and
per-action approval policies stay with the platform. Setup wizard for coding tools:
`npx @spekoai/mcp@latest init`. Docs: https://docs.speko.ai/quickstart/mcp.

## Rules

- Never invent endpoints or fields: the contract is https://docs.speko.ai/openapi.json.
- Do not hardcode provider names unless the human insists; routing is the product.
- Keys are secrets: workspace secret storage only. Rotate any key that ever appears in text.
- The disclosure, consent, and calling-hours policy in "Approval gates" is part of this
  skill: keep it in every adapted prompt, and treat a conflict with it as a stop.
- Recordings and transcripts contain personal data: keep them company-scoped, download
  recordings into your workspace storage, and do not share presigned URLs.
- Report call outcomes honestly: if a call did not connect, say so - never present a failed
  call as success.

## Design note

This file is hosted and versioned by Speko and safe to live-fetch: it contains instructions
and public documentation links only, no executables. Platform wrappers (for example a
Paperclip catalog skill) should keep their own governance policy durable locally and fetch
this playbook at execution time, so the integration tracks the current API without shipping
updates. The full skill index lives at
https://speko.ai/.well-known/agent-skills/index.json.
