---
title: "How to add phone calls to your own AI agent"
description: "Give an agent you're building a phone: connect CallForMe over MCP, or call its REST API from TypeScript. A working example you can run on a free demo line."
url: https://callforme.tel/guides/add-phone-calls-to-your-ai-agent
published: 2026-10-03
updated: 2026-10-03
author: CallForMe team, Great Work LLC
---

# How to add phone calls to your own AI agent

> If your agent framework can connect to a remote MCP server, point it at https://callforme.tel/mcp and it gets place_call, get_call and the other tools. Otherwise use the REST API: POST /v1/calls to dial, GET /v1/calls/:id?wait=45 to follow it, and POST /v1/calls/:id/answer when the business asks something. No telephony or voice setup on your side.

## Two ways in

**MCP.** If you're building on a framework that can use remote MCP servers, add `https://callforme.tel/mcp` as a server. Your model gets the same tools Claude and ChatGPT use: `plan_call`, `place_call`, `get_call`, `answer_question`, `call_around` and the rest, with descriptions written for models. Connecting needs no key; the first real call hands back a setup link. See the [MCP reference](/docs/mcp).

**REST.** If you'd rather wrap it as your own tool, the API at `https://callforme.tel/v1` has the same behavior over plain HTTP. The rest of this page walks through it in TypeScript. The full endpoint list is in the [REST API docs](/docs/rest-api), and the spec is at [/openapi.json](/openapi.json).

## 1. Place a call

```ts
const BASE = "https://callforme.tel/v1";
const KEY = process.env.CALLFORME_KEY; // not needed for demo lines
const headers: Record<string, string> = { "Content-Type": "application/json" };
if (KEY) headers.Authorization = `Bearer ${KEY}`;

const placed = await fetch(`${BASE}/calls`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    phone: "+14697707412", // Maple Street Pizza, a free fictional demo line
    business_name: "Maple Street Pizza",
    goal: "Ask how long a large pepperoni takes for pickup right now.",
    questions: ["How many minutes for a large pepperoni?"],
    on_behalf_of: "Sam",
  }),
}).then((r) => r.json());

if (placed.status === "needs_setup") {
  // First real call on a new account: show this to your user, then retry with setup_code.
  console.log(placed.message_for_user);
  process.exit(0);
}
const callId: string = placed.call_id;
```

The request takes the same fields as the MCP `place_call` tool: `details` for facts the business may ask for, `if_asked` for pre-approved answers, `constraints` for hard limits, `callback_number`, `voicemail_message`, `transfer_to` and `language`. See [how to write a good call goal](/guides/write-a-good-call-goal).

## 2. Follow it and answer questions

Long-poll with `wait=45`. The request returns early when something needs you: a question from the business, a new answer, or the end of the call.

```ts
async function ask(question: string): Promise<string> {
  // Answer from your agent's context, or ask your user. Return quickly:
  // the business is waiting on the line.
  return "Pickup, under the name Sam.";
}

let call: any;
do {
  call = await fetch(`${BASE}/calls/${callId}?wait=45&transcript=none`, { headers }).then((r) => r.json());
  if (call.pending_question) {
    const answer = await ask(call.pending_question);
    await fetch(`${BASE}/calls/${callId}/answer`, {
      method: "POST",
      headers,
      body: JSON.stringify({ answer, question_id: call.pending_question_id }),
    });
  }
} while (call.status !== "ended" || !call.outcome);

console.log(call.outcome.summary);
console.log(call.answers);
```

If your code doesn't answer within about 45 seconds, the assistant tells the business the customer will follow up on that point and carries on, so a slow answer never leaves anyone hanging. The same `/answer` endpoint steers a live call at any time: `{"answer": "Also ask if they deliver."}`.

## 3. Use the result

A finished call gives you structured fields, so your agent doesn't have to parse a transcript:

- `outcome.type`: `booked`, `quoted`, `answered`, `cancelled`, `voicemail`, `refused_ai` and a few more
- `outcome.summary`: one sentence for your user
- `answers`: one entry per question, in your order, `null` when unanswered
- `outcome.price_quoted`, `outcome.booked_time`, `outcome.confirmation_number` when they apply
- `cost`: what the call cost

Add `transcript=full` when you want every line. See [transcripts and recordings](/guides/ai-call-transcript-and-recording).

## 4. Expose it as one tool

Most agents work best with a single tool that does the whole call. Describe it plainly and let the model fill in the fields:

```ts
const phoneTool = {
  name: "call_business",
  description: "Phone a US or Canadian business and get something done: book, cancel, get a price or hours. Returns the outcome and answers.",
  input_schema: {
    type: "object",
    properties: {
      phone: { type: "string" },
      goal: { type: "string", description: "What the call should get done, 1 to 3 sentences" },
      questions: { type: "array", items: { type: "string" } },
      details: { type: "string", description: "Facts the business may ask for. Never card numbers." },
    },
    required: ["phone", "goal"],
  },
};
```

Run steps 1 to 3 inside the tool and return `outcome` and `answers` to the model. For quotes from several places, use `POST /v1/calls/around` instead of a loop of single calls: the server finds the businesses, paces the dialing, and returns one results table. See [call around](/guides/call-around).

## What you don't have to build

No phone numbers, carrier registration, voice models, menu navigation, hold detection, voicemail detection, transcription or call recording. Calls open with an AI disclosure, respect business-local quiet hours (10pm to 7am), and honor opt-outs across every customer. Compare that with [building on Twilio yourself](/compare/twilio-diy).

## Cost

Demo lines are free. Real calls are $1 per answered call including the first 5 minutes, then $0.25 a minute, from a prepaid balance. Unanswered and busy calls are free. See [pricing](/docs/pricing).

## FAQ

### Do I need my own phone number or voice provider?

No. CallForMe places the call from its own number, runs the voice, and handles menus and hold. Your code sends a goal and reads back the result.

### Can I try it without an account?

Yes. Calls to the fictional demo lines need no key and cost nothing, up to 12 a day. The example on this page calls one.

### How does my agent get a key for real calls?

The first real call returns needs_setup with a link. A person opens it and adds $10 of credit, the retry dials, and the response includes account_key once. Save it and send it as a Bearer token.

### How should I handle the business's questions?

Poll with wait=45. When pending_question is set, answer it with POST /v1/calls/:id/answer within about 45 seconds, from context or by asking your user.

## Related

- [REST API](https://callforme.tel/docs/rest-api.md)
- [MCP server reference](https://callforme.tel/docs/mcp.md)
- [Twilio DIY vs CallForMe for AI phone calls](https://callforme.tel/compare/twilio-diy.md)
- [Use CallForMe in n8n, Zapier, and Make](https://callforme.tel/agents/automations.md)
- [Meta Muse vs CallForMe: a Muse alternative in your own agent](https://callforme.tel/compare/meta-muse-alternative.md)
