@getdial/ai-sdk
v0.16.0
Published
Official Dial tools for the Vercel AI SDK — phone numbers, SMS, and AI voice calls for any tool-calling model
Readme
@getdial/ai-sdk
Official Dial tools for the Vercel AI SDK — give any tool-calling model the ability to send SMS and place AI voice calls through Dial.
It's the TypeScript analog of dial-langchain:
a thin adapter that wraps the @getdial/sdk
client in AI SDK tool() definitions. It adds nothing to the REST contract — it
just shapes Dial's operations the way the AI SDK wants them.
Not Vercel-only. The "Vercel AI SDK" is the open-source
aipackage; it runs on any JS host (Next.js anywhere, Node, Hono, Workers, Deno, Bun) and with any tool-calling model (Claude, GPT, Gemini, …). These tools work wherever it does.
Install
npm install @getdial/ai-sdk ai zodai and zod are peer dependencies — your app already has them.
Give the tools to a model
Build one DialClient, pass it to dialTools, and spread the result into the tools
field. Every tool shares that one client (a single connection pool). To switch models,
change one line; the tools don't change.
import { streamText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { DialClient } from "@getdial/sdk";
import { dialTools } from "@getdial/ai-sdk";
const dial = new DialClient({ apiKey: process.env.DIAL_API_KEY! });
const result = streamText({
model: anthropic("claude-opus-4-8"), // or openai("gpt-5"), google("gemini-2.5-pro"), …
tools: dialTools(dial, {
fromNumberId: process.env.DIAL_FROM_NUMBER_ID, // optional default "from"
}),
messages,
});In a Next.js app this lives in a route handler (app/api/chat/route.ts); the host
is irrelevant.
Pick individual tools
When you only want a subset, import the factories directly and pass them the same client:
import { DialClient } from "@getdial/sdk";
import { sendMessageTool, makeCallTool } from "@getdial/ai-sdk";
const dial = new DialClient({ apiKey: process.env.DIAL_API_KEY! });
const tools = {
sendMessage: sendMessageTool(dial, { fromNumberId: "pn_..." }),
makeCall: makeCallTool(dial, { fromNumberId: "pn_..." }),
};Available tools
| Tool | Action |
|---|---|
| listNumbers | List your phone numbers |
| purchaseNumber | Provision a new number (billable) |
| setNumberProperties | Update a number's nickname / inbound instruction / voice / duration cap |
| sendMessage | Send an SMS (optionally MMS) |
| replyToMessage | Reply or react to a message |
| listMessages | List recent messages |
| makeCall | Place an AI voice call |
| listCalls | List recent calls |
| getCall | Fetch one call by id |
| getBilling | Wallet balance, subscription, per-number mode |
| waitForMessage | Block until the next inbound SMS arrives, or time out |
If fromNumberId is set in the options, it's the default for sendMessage and
makeCall — the model can omit it.
Send a code and await the reply
waitForMessage pairs with sendMessage so the model can verify a number inside
a single turn:
const dial = new DialClient({ apiKey: process.env.DIAL_API_KEY! });
const tools = dialTools(dial, { fromNumberId: "pn_..." });
await generateText({
model,
tools,
// The model sends a code via sendMessage, then calls waitForMessage to read the reply.
prompt: "Text +14155550123 the code 4821, then wait up to 60s for their reply and tell me if it matches.",
});Notes
sendMessageis a write action and isn't idempotent — a re-invoke after a failure can send a duplicate.makeCallaccepts anidempotencyKey: re-invoking with the same key returns the already-placed call instead of dialing again.waitForMessageis backed by Dial's presence-based event stream — missed events replay only on reconnect within ~2 minutes. For durable, at-least-once delivery, register a webhook.
See the Vercel AI SDK integration docs for the full guide.
