Torna alle risorse
Guida strumenti · · 8 min di lettura

Come creare un agente vocale con Claude Code e ElevenLabs in 15 minuti

Guida pratica per creare un agente vocale che risponde sulle pagine del sito e prenota appuntamenti, con Claude Code ed ElevenLabs.

Cosa stai costruendo davvero

Fino a poco tempo fa, creare un voice agent richiedeva mesi di lavoro, specialisti diversi e tanta infrastruttura da incollare insieme. Oggi non è più così.

In questa guida costruisci un agente vocale funzionante che:

  • risponde alle domande sul tuo sito,
  • prenota appuntamenti a calendario,
  • usa Claude Code + ElevenLabs,
  • si mette in piedi in circa 15 minuti di setup effettivo.

Non serve un background di audio engineering. Non serve uno stack proprietario di telefonia.

Alla fine avrai un agente che:

  • ascolta e risponde in linguaggio naturale parlato (speech-to-text + text-to-speech di ElevenLabs),
  • usa Claude come motore di ragionamento per capire intent e generare risposte,
  • controlla il calendario e prenota slot su comando,
  • usa il contesto del tuo sito per rispondere in modo accurato.

Andiamo.

Prerequisiti

Prima di iniziare, prepara tutto questo.

Account

  • Un account ElevenLabs (il piano free va bene per test; il paid migliora qualità voce e limiti)
  • Una API key Anthropic per Claude da Anthropic Console
  • Un account Google (se vuoi integrazione Google Calendar)

Tool

  • Node.js 18+
  • Claude Code CLI installato (npm install -g @anthropic-ai/claude-code)
  • Un minimo di confidenza con terminale (non devi programmare tanto, ma qualche comando sì)

Tempo stimato: 15–25 minuti per un prototipo funzionante. Aggiungi 30–60 minuti se vuoi personalizzare voce, knowledge base o logica calendario.

Step 1 — Configura la voce in ElevenLabs

ElevenLabs gestisce sia output voce (TTS) sia input voce (STT). Setup iniziale: circa 3 minuti.

Crea un agente Conversational AI in ElevenLabs

  1. Vai nella dashboard ElevenLabs → Conversational AI.
  2. Clicca Create Agent.
  3. Scegli una voce base (per booking: tono professionale e neutro).
  4. Nel campo System Prompt, incolla una descrizione breve del ruolo, ad esempio:

“Sei un assistente utile per [Nome Azienda]. Rispondi alle domande sui nostri servizi e aiuti i visitatori a prenotare appuntamenti. Sii conciso, cordiale e professionale.”

  1. Salva l’Agent ID.
  2. Recupera la API key ElevenLabs da Settings → API Keys.

Imposta voce e turn-taking

Nelle impostazioni agente trovi:

  • Interruption sensitivity: quanto facilmente l’agente si ferma se l’utente interrompe
  • Response latency: parti da “balanced”
  • Voice stability / similarity boost: lascia default se non devi rifinire il timbro

Fine setup iniziale ElevenLabs. WebSocket, streaming audio e voice activity detection sono già gestiti dalla piattaforma.

Step 2 — Collega Claude Code come cervello

Claude Code è l’agente di coding Anthropic nel terminale. Qui lo usi come livello di ragionamento: interpreta intent e decide azioni.

Inizializza il progetto

Nel terminale:

mkdir voice-agent && cd voice-agent
npm init -y
npm install @anthropic-ai/sdk dotenv node-fetch

Crea .env:

ANTHROPIC_API_KEY=your_key_here
ELEVENLABS_API_KEY=your_key_here
ELEVENLABS_AGENT_ID=your_agent_id_here
GOOGLE_CALENDAR_ID=your_calendar_id_here

Collega Claude all’agente ElevenLabs

ElevenLabs Conversational AI supporta endpoint LLM custom. Quindi puoi usare Claude al posto del modello default.

  1. In ElevenLabs → impostazioni agente → LLM Settings
  2. Seleziona Custom LLM
  3. Punta a un proxy leggero (locale o deployato) che inoltra chiamate ad Anthropic API

Crea claude-proxy.js:

const Anthropic = require("@anthropic-ai/sdk");
const http = require("http");
require("dotenv").config();

const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

const server = http.createServer(async (req, res) => {
  if (req.method !== "POST") return res.end();

  let body = "";
  req.on("data", (chunk) => (body += chunk));
  req.on("end", async () => {
    const payload = JSON.parse(body);

    const response = await client.messages.create({
      model: "claude-opus-4-5",
      max_tokens: 1024,
      system: payload.system || "",
      messages: payload.messages,
    });

    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(
      JSON.stringify({
        choices: [{ message: { content: response.content[0].text } }],
      })
    );
  });
});

server.listen(3000, () => console.log("Claude proxy running on port 3000"));

Avvio:

node claude-proxy.js

In produzione, lo deployi e punti ElevenLabs all’URL pubblico.

Step 3 — Aggiungi prenotazione calendario

Qui l’agente smette di essere “solo chat” e diventa utile davvero.

Configura accesso a Google Calendar

  1. Crea progetto in Google Cloud Console
  2. Abilita Google Calendar API
  3. Crea Service Account e scarica JSON credenziali
  4. Condividi il calendario Google con email del service account (permesso: modifica eventi)
  5. Salva il file come google-credentials.json nella root progetto

Installa libreria:

npm install googleapis

Crea tool calendario

calendar.js:

const { google } = require("googleapis");

const auth = new google.auth.GoogleAuth({
  keyFile: "google-credentials.json",
  scopes: ["https://www.googleapis.com/auth/calendar"],
});

const calendar = google.calendar({ version: "v3", auth });

async function getAvailableSlots(date) {
  const start = new Date(date);
  start.setHours(9, 0, 0, 0);
  const end = new Date(date);
  end.setHours(17, 0, 0, 0);

  const res = await calendar.freebusy.query({
    requestBody: {
      timeMin: start.toISOString(),
      timeMax: end.toISOString(),
      items: [{ id: process.env.GOOGLE_CALENDAR_ID }],
    },
  });

  const busy = res.data.calendars[process.env.GOOGLE_CALENDAR_ID].busy;
  return generateSlots(start, end, busy); // semplificato: slot da 30 minuti
}

async function bookAppointment({ name, email, date, time, duration = 30 }) {
  const startTime = new Date(`${date}T${time}`);
  const endTime = new Date(startTime.getTime() + duration * 60000);

  await calendar.events.insert({
    calendarId: process.env.GOOGLE_CALENDAR_ID,
    requestBody: {
      summary: `Appointment with ${name}`,
      description: `Contact: ${email}`,
      start: { dateTime: startTime.toISOString() },
      end: { dateTime: endTime.toISOString() },
      attendees: [{ email }],
    },
  });

  return { success: true, slot: `${date} at ${time}` };
}

module.exports = { getAvailableSlots, bookAppointment };

Registra i tool per Claude

Aggiorna il proxy esponendo i tool come function-calls (schema JSON):

const tools = [
  {
    name: "get_available_slots",
    description: "Check available appointment slots for a given date",
    input_schema: {
      type: "object",
      properties: {
        date: { type: "string", description: "Date in YYYY-MM-DD format" },
      },
      required: ["date"],
    },
  },
  {
    name: "book_appointment",
    description: "Book an appointment for a user",
    input_schema: {
      type: "object",
      properties: {
        name: { type: "string" },
        email: { type: "string" },
        date: { type: "string" },
        time: { type: "string", description: "Time in HH:MM format" },
      },
      required: ["name", "email", "date", "time"],
    },
  },
];

Passa tools a client.messages.create(). Quando Claude ritorna tool_use, esegui la funzione di calendar.js e restituisci tool_result.

Step 4 — Aggiungi layer Q&A del sito

Il booking agent è più forte se risponde anche a domande su servizi, prezzi, orari, policy.

Scraping + contenuto contestuale

Per una soluzione rapida, preprocessi il contenuto del sito in un file testo da iniettare nel system prompt.

Installa:

npm install cheerio

Crea scrape-site.js:

const fetch = require("node-fetch");
const cheerio = require("cheerio");
const fs = require("fs");

async function scrapePages(urls) {
  let content = "";

  for (const url of urls) {
    const res = await fetch(url);
    const html = await res.text();
    const $ = cheerio.load(html);

    $("nav, footer, script, style").remove();
    const text = $("body").text().replace(/\s+/g, " ").trim();
    content += `\n\n--- ${url} ---\n${text}`;
  }

  fs.writeFileSync("site-content.txt", content);
  console.log("Site content saved.");
}

scrapePages([
  "https://yoursite.com",
  "https://yoursite.com/services",
  "https://yoursite.com/pricing",
  "https://yoursite.com/faq",
]);

Esegui una volta:

node scrape-site.js

Inietta contesto nel system prompt

Nel proxy:

const siteContent = fs.readFileSync("site-content.txt", "utf8");

const systemPrompt = `You are a helpful voice assistant for [Your Business].

Use the following website content to answer questions accurately:

${siteContent}

When a user wants to book an appointment, collect their name, email, preferred date, and preferred time. Then use the available tools to check slots and confirm the booking.

Keep responses concise — this is a voice conversation, so avoid long lists or complex formatting.`;

La parte “keep responses concise” è fondamentale: ciò che è leggibile in testo spesso è innaturale se letto ad alta voce.

Step 5 — Testa l’agente vocale

A questo punto hai:

  • ElevenLabs per input/output voce,
  • Claude per ragionamento e conversazione,
  • Google Calendar per disponibilità e booking,
  • contenuto sito come base conoscenza.

Test locale

Avvia proxy:

node claude-proxy.js

Se ElevenLabs deve raggiungere il tuo proxy locale, usa ngrok:

ngrok http 3000

Copia URL HTTPS di ngrok e incollalo nel campo Custom LLM URL di ElevenLabs.

Prova frasi tipo:

  • “Che servizi offrite?”
  • “Vorrei prenotare un appuntamento per martedì prossimo.”
  • “Avete disponibilità venerdì pomeriggio?”

Guarda il terminale: vedrai quando Claude usa tool calendario e quando risponde dal contenuto sito.

Problemi comuni

Latenza alta Opus è più lento di Haiku/Sonnet. Se è lento, prova claude-haiku-4-5 nel proxy.

Tool call non eseguite Controlla il loop tool_use -> function execution -> tool_result. Se manca, Claude si blocca.

Risposte troppo lunghe Aggiungi nel prompt: “Limita tutte le risposte a 2–3 frasi, salvo richiesta di dettaglio”.

Errore permessi calendario Assicurati che il calendario sia condiviso con email del service account.

Step 6 — Deploy in produzione

Il locale basta per test. In produzione serve hosting pubblico del proxy.

Opzioni rapide

  • Railway / Render: deploy da repo GitHub in pochi click
  • Vercel Edge Functions: opzione serverless (attenzione ai cold start)
  • Fly.io: ottimo per scegliere regione e ridurre latenza

Dopo deploy, aggiorna l’LLM URL in ElevenLabs verso il server di produzione. Poi integra il widget vocale nel sito con snippet ElevenLabs, oppure usa SDK per UI custom.

Dove entra MindStudio in questo stack

Se vuoi estendere il voice agent senza scrivere altro backend, il plugin Agent Skills di MindStudio è utile.

È un SDK npm (@mindstudio-ai/agent) che dà a un agente AI accesso a 120+ capability tipizzate via metodi semplici. Esempi:

  • agent.sendEmail()
  • agent.searchGoogle()
  • agent.runWorkflow()

Con integrazioni pronte per HubSpot, Salesforce, Google Workspace, Slack e altro.

Invece di scrivere codice custom ogni volta che vuoi una nuova azione (email conferma, log CRM, notifica Slack), chiami un metodo e SDK gestisce auth, rate limit, retry.

Esempio pratico post-booking:

const { MindStudio } = require("@mindstudio-ai/agent");
const agent = new MindStudio(process.env.MINDSTUDIO_API_KEY);

await agent.sendEmail({
  to: userEmail,
  subject: "Your appointment is confirmed",
  body: `Hi ${userName}, your appointment is confirmed for ${slot}.`,
});

await agent.runWorkflow("hubspot-contact-create", {
  email: userEmail,
  name: userName,
  source: "voice-agent",
});

Così Claude resta focalizzato sul ragionamento, mentre MindStudio gestisce il layer integrazioni.

Per chi vuole evitare del tutto il codice, il visual builder di MindStudio permette anche di costruire agenti AI senza il setup proxy descritto sopra.

FAQ

Quanto costa far girare un agente vocale così?

Dipende dal volume. ElevenLabs fattura per caratteri TTS (circa $0.30 / 1.000 caratteri su Starter). Claude varia per modello: Haiku costa molto meno di Opus a volume alto. Google Calendar API è gratuita in quote generose. Per una PMI con poche decine di chiamate giorno, spesso resti sotto $50/mese.

Posso usare un calendario diverso da Google?

Sì. Il modulo calendario è modulare. Puoi sostituire Google con Calendly, Outlook (Microsoft Graph) o altri API calendar. Le definizioni tool per Claude restano uguali: cambia solo l’esecuzione sotto.

Differenza tra LLM default ElevenLabs e Claude collegato?

Il default ElevenLabs è ottimizzato per bassa latenza ma con ragionamento meno profondo. Per FAQ semplici va bene. Per richieste sfumate, booking multi-step e disponibilità ambigue, Claude è nettamente migliore. Tradeoff: più latenza, mitigabile con Haiku al posto di Opus.

Come tengo aggiornato il contenuto del sito?

Approccio semplice: cron job notturno che rilancia scraping e riavvia proxy con contenuto fresco. Approccio robusto: vector DB (es. Pinecone, Weaviate) + RAG per aggiornare pagine senza re-embedding totale. Per siti piccoli, il cron notturno è spesso sufficiente.

È production-ready o solo prototipo?

Architettura pronta, ma va irrobustita prima di utenti reali:

  • error handling e fallback quando API non rispondono,
  • rate limiting nel proxy,
  • logging qualità conversazioni,
  • test edge-case (dati parziali, richieste fuori orario).

Il core è solido. Il lavoro produzione è nel controllo errori.

Posso aggiungere voce a un chatbot già esistente?

Sì, ed è un caso comune. Se hai già chatbot Claude con prompt + tool, puoi aggiungere layer voce ElevenLabs con sforzo contenuto. L’aggiustamento principale è riscrivere il system prompt per risposte brevi e adatte al parlato.

Key takeaways

  • In meno di 30 minuti puoi avere un voice agent con booking calendario e Q&A sito usando Claude Code, ElevenLabs e Google Calendar API.
  • ElevenLabs gestisce voce I/O; Claude gestisce ragionamento e orchestrazione tool; calendario gestisce scheduling.
  • Se la latenza è alta, passare da Opus a Haiku è la leva più rapida.
  • Iniettare il contenuto sito nel system prompt è un approccio rapido e leggero per Q&A, ideale su siti con aggiornamenti non frequenti.
  • Per estendere capacità senza altro backend, il plugin MindStudio Agent Skills espone 120+ integrazioni via method call.

Se vuoi estendere ancora, per esempio con logging CRM, email conferma, notifiche Slack, o una console no-code per gestire l’agente, puoi esplorare MindStudio e i loro flussi di AI workflow automation.


Articolo originale: https://www.mindstudio.ai/blog/build-voice-agent-claude-code-elevenlabs

Vuoi implementare queste soluzioni?

Parliamone in una call gratuita di 30 minuti.

Prenota una call