Datenerfassung und -analyse mit Agents Platform in Next.js

Erfassen und analysieren Sie Daten in Post-Call-Webhooks mit Agents Platform und Next.js.

Tutorial · Setzt voraus, dass Sie den ElevenAgents- Schnellstart abgeschlossen und ein Next.js-Projekt eingerichtet haben.

Einführung

In diesem Tutorial lernen Sie, wie Sie einen Voice-Agent entwickeln, der über Gespräche Informationen von Nutzern erfasst, die Daten dann strukturiert analysiert und extrahiert und sie über den Post-Call-Webhook an Ihre Anwendung sendet.

Voraussetzungen

  • Ein ElevenLabs-Konto mit einem API-Schlüssel.
  • Node.js v18 oder höher, installiert auf Ihrem Rechner.

Einrichtung

Neues Next.js-Projekt erstellen

Wir empfehlen unsere v0.dev-Agents-Platform-Vorlage als Ausgangspunkt für Ihre Anwendung. Diese Vorlage ist eine produktionsreife Next.js-Anwendung mit bereits integriertem ElevenLabs-Agent.

Agents Platform einrichten

Folgen Sie unserer Next.js-Anleitung für die Installations- und Konfigurationsschritte. Kehren Sie dann hierher zurück, um die erweiterten Funktionen zu entwickeln.

Agent-Konfiguration

1

Bei ElevenLabs anmelden

Gehen Sie zu elevenlabs.io und melden Sie sich bei Ihrem Konto an.

2

Neuen Agenten erstellen

Navigieren Sie zu Agents Platform > Agents und erstellen Sie einen neuen Agenten anhand der leeren Vorlage.

3

Erste Nachricht festlegen

Legen Sie die erste Nachricht fest und geben Sie die dynamische Variable für die Plattform an.

Hi {{user_name}}, I'm Jess from the ElevenLabs team. I'm here to help you design your very own ElevenLabs agent! To kick things off, let me know what kind of agent you're looking to create. For example, do you want a support agent, to help your users answer questions, or a sales agent to sell your products, or just a friend to chat with?
4

System-Prompt festlegen

Legen Sie den System-Prompt fest. Sie können hier auch dynamische Variablen einfügen.

You are Jess, a helpful agent helping {{user_name}} to design their very own ElevenLabs agent. The design process involves the following steps:
"initial": In the first step, collect the information about the kind of agent the user is looking to create. Summarize the user's needs back to them and ask if they are ready to continue to the next step. Only once they confirm proceed to the next step.
"training": Tell the user to create the agent's knowledge base by uploading documents, or submitting URLs to public websites with information that should be available to the agent. Wait patiently without talking to the user. Only when the user confirms that they've provided everything then proceed to the next step.
"voice": Tell the user to describe the voice they want their agent to have. For example: "A professional, strong spoken female voice with a slight British accent." Repeat the description of their voice back to them and ask if they are ready to continue to the next step. Only once they confirm proceed to the next step.
"email": Tell the user that we've collected all necessary information to create their ElevenLabs agent and ask them to provide their email address to get notified when the agent is ready.
Always call the `set_ui_state` tool when moving between steps!
5

Client-Tools einrichten

Richten Sie das folgende Client-Tool ein, um zwischen den Schritten zu navigieren:

  • Name: set_ui_state
    • Beschreibung: Verwenden Sie dieses clientseitige Tool, um zwischen den verschiedenen UI-Zuständen zu navigieren.
    • Auf Antwort warten: true
    • Antwort-Timeout (Sekunden): 1
    • Parameter:
      • Datentyp: string
      • Kennung: step
      • Erforderlich: true
      • Werttyp: LLM-Prompt
      • Beschreibung: Der Schritt, zu dem in der UI navigiert werden soll. Verwenden Sie nur die Schritte, die im System-Prompt definiert sind.
6

Stimme Ihres Agenten festlegen

Navigieren Sie zum Tab Voice und legen Sie die Stimme für Ihren Agenten fest. Eine Liste empfohlener Stimmen für die Agents Platform finden Sie in der Dokumentation zum Conversational Voice Design.

7

Bewertungskriterien festlegen

Navigieren Sie zum Tab Analysis und fügen Sie ein neues Bewertungskriterium hinzu.

  • Name: all_data_provided
    • Prompt: Bewerten Sie, ob der Nutzer eine Beschreibung des Agenten angegeben hat, den er erstellen möchte, sowie eine Beschreibung der Stimme, die der Agent haben soll.
8

Datenerfassung konfigurieren

Sie können die Analyse nach dem Anruf nutzen, um Daten aus dem Gespräch zu extrahieren. Fügen Sie im Tab Analysis unter Data Collection die folgenden Elemente hinzu:

  • Kennung: voice_description
    • data-type: String
    • Beschreibung: Erstellen Sie anhand der Beschreibung der Stimme, die der Nutzer für den Agenten wünscht, eine prägnante Stimmbeschreibung mit Alter, Akzent, Tonfall und Charakter, sofern verfügbar.
  • Kennung: agent_description
    • data-type: String
    • Beschreibung: Erstellen Sie anhand der Beschreibung des Agenten, den der Nutzer entwerfen möchte, einen Prompt, mit dem ein Modell trainiert werden kann, als dieser Agent zu agieren.
9

Post-Call-Webhook konfigurieren

Post-Call-Webhooks benachrichtigen Sie, wenn ein Anruf endet und die Analyse- und Datenextraktionsschritte abgeschlossen sind.

In diesem Beispiel führt der Post-Call-Webhook mehrere Schritte aus:

  1. Erstellen einer benutzerdefinierten Stimmgestaltung basierend auf der voice_description.
  2. Erstellen eines ElevenLabs-Agenten für die Nutzer basierend auf der angegebenen agent_description.
  3. Abrufen der Wissensdatenbankdokumente aus dem in Redis gespeicherten Gesprächszustand und Anhängen der Wissensdatenbank an den Agenten.
  4. Senden einer E-Mail an den Nutzer, um ihn darüber zu informieren, dass sein benutzerdefinierter ElevenLabs-Agent bereit zum Chatten ist.

Wenn Sie lokal arbeiten, benötigen Sie ein Tool wie ngrok, um Ihren lokalen Server über das Internet verfügbar zu machen.

ngrok http 3000

Navigieren Sie zu den Agents-Platform-Einstellungen und erstellen Sie unter Post-Call Webhook einen neuen Webhook. Fügen Sie Ihre ngrok-URL ein: https://<your-url>.ngrok-free.app/api/convai-webhook.

Nach dem Speichern des Webhooks erhalten Sie ein Webhook-Secret. Bewahren Sie dieses Secret sicher auf, da Sie es später in Ihrer .env-Datei festlegen müssen.

Erweiterte Funktionen integrieren

Redis-Datenbank zum Speichern des Gesprächszustands einrichten

In diesem Beispiel verwenden wir Redis, um den Gesprächszustand zu speichern. So können wir die Wissensdatenbankdokumente nach Ende des Anrufs aus dem Gesprächszustand abrufen.

Wenn Sie auf Vercel bereitstellen, können Sie die Integration Upstash for Redis konfigurieren. Alternativ können Sie sich für ein kostenloses Upstash-Konto registrieren und eine neue Datenbank erstellen.

Resend zum Senden von E-Mails nach dem Anruf einrichten

In diesem Beispiel verwenden wir Resend, um dem Nutzer nach dem Anruf eine E-Mail zu senden. Dazu müssen Sie ein kostenloses Resend-Konto erstellen und einen neuen API-Key einrichten.

Umgebungsvariablen festlegen

Erstellen Sie im Stammverzeichnis Ihres Projekts eine .env-Datei und fügen Sie die folgenden Variablen hinzu:

ELEVENLABS_CONVAI_WEBHOOK_SECRET=
ELEVENLABS_API_KEY=
ELEVENLABS_AGENT_ID=
# Resend
RESEND_API_KEY=
RESEND_FROM_EMAIL=
# Upstash Redis
KV_URL=
KV_REST_API_READ_ONLY_TOKEN=
REDIS_URL=
KV_REST_API_TOKEN=
KV_REST_API_URL=

Sicherheit und Authentifizierung konfigurieren

Um Ihren ElevenLabs-Agenten abzusichern, müssen Sie die Authentifizierung im Tab Security der Agent-Konfiguration aktivieren.

Sobald die Authentifizierung aktiviert ist, müssen Sie in einer sicheren serverseitigen Umgebung eine signierte URL erstellen, um ein Gespräch mit dem Agenten zu beginnen. In Next.js können Sie dies durch das Einrichten einer neuen API-Route tun.

./app/api/signed-url/route.ts
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { NextResponse } from "next/server";
export async function GET() {
const agentId = process.env.ELEVENLABS_AGENT_ID;
if (!agentId) {
throw Error("ELEVENLABS_AGENT_ID is not set");
}
try {
const elevenlabs = new ElevenLabsClient();
const response = await elevenlabs.conversationalAi.conversations.getSignedUrl({
agentId,
});
return NextResponse.json({ signedUrl: response.signedUrl });
} catch (error) {
console.error("Error:", error);
return NextResponse.json({ error: "Failed to get signed URL" }, { status: 500 });
}
}

Gesprächssitzung starten

Um das Gespräch zu starten, rufen Sie zuerst Ihre API-Route auf, um die signierte URL abzurufen. Verwenden Sie dann den Hook useConversation, um die Gesprächssitzung einzurichten.

./page.tsx
import { useConversation } from "@elevenlabs/react";
async function getSignedUrl(): Promise<string> {
const response = await fetch("/api/signed-url");
if (!response.ok) {
throw Error("Failed to get signed url");
}
const data = await response.json();
return data.signedUrl;
}
export default function Home() {
// ...
const [currentStep, setCurrentStep] = useState<
"initial" | "training" | "voice" | "email" | "ready"
>("initial");
const [conversationId, setConversationId] = useState("");
const [userName, setUserName] = useState("");
const conversation = useConversation({
onConnect: () => console.log("Connected"),
onDisconnect: () => console.log("Disconnected"),
onMessage: (message: string) => console.log("Message:", message),
onError: (error: Error) => console.error("Error:", error),
});
const startConversation = useCallback(async () => {
try {
// Request microphone permission
await navigator.mediaDevices.getUserMedia({ audio: true });
// Start the conversation with your agent
const signedUrl = await getSignedUrl();
const convId = await conversation.startSession({
signedUrl,
dynamicVariables: {
user_name: userName,
},
clientTools: {
set_ui_state: ({ step }: { step: string }): string => {
// Allow agent to navigate the UI.
setCurrentStep(step as "initial" | "training" | "voice" | "email" | "ready");
return `Navigated to ${step}`;
},
},
});
setConversationId(convId);
console.log("Conversation ID:", convId);
} catch (error) {
console.error("Failed to start conversation:", error);
}
}, [conversation, userName]);
const stopConversation = useCallback(async () => {
await conversation.endSession();
}, [conversation]);
// ...
}

Client-Tool und dynamische Variablen

In der vorherigen Agent-Konfiguration haben Sie das Client-Tool set_ui_state registriert, damit der Agent zwischen verschiedenen UI-Zuständen navigieren kann. Um alles zusammenzuführen, müssen Sie die Implementierung des Client-Tools an die Optionen von conversation.startSession übergeben.

Hier können Sie auch die dynamischen Variablen an das Gespräch übergeben.

./page.tsx
const convId = await conversation.startSession({
signedUrl,
dynamicVariables: {
user_name: userName,
},
clientTools: {
set_ui_state: ({ step }: { step: string }): string => {
// Allow agent to navigate the UI.
setCurrentStep(step as "initial" | "training" | "voice" | "email" | "ready");
return `Navigated to ${step}`;
},
},
});

Dokumente in die Wissensdatenbank hochladen

Im Schritt Training fordert der Agent den Nutzer auf, Dokumente hochzuladen oder URLs zu öffentlichen Websites mit Informationen einzureichen, die seinem Agenten zur Verfügung stehen sollen. Hier können Sie die neue Funktion after von Next.js 15 nutzen, um Dokumente im Hintergrund hochzuladen.

Erstellen Sie eine neue Server-Aktion upload, um die Erstellung der Wissensdatenbank bei der Formularübermittlung zu verarbeiten. Sobald alle Wissensdatenbankdokumente erstellt wurden, speichern Sie die Gesprächs-ID und die Wissensdatenbank-IDs in der Redis-Datenbank.

./app/actions/upload.ts
"use server";
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { Redis } from "@upstash/redis";
import { redirect } from "next/navigation";
import { after } from "next/server";
// Initialize Redis
const redis = Redis.fromEnv();
const elevenlabs = new ElevenLabsClient({
apiKey: process.env.ELEVENLABS_API_KEY,
});
export async function uploadFormData(formData: FormData) {
const knowledgeBase: Array<{
id: string;
type: "file" | "url";
name: string;
}> = [];
const files = formData.getAll("file-upload") as File[];
const email = formData.get("email-input");
const urls = formData.getAll("url-input");
const conversationId = formData.get("conversation-id");
after(async () => {
// Upload files as background job
// Create knowledge base entries
// Loop through files and create knowledge base entries
for (const file of files) {
if (file.size > 0) {
const response = await elevenlabs.conversationalAi.knowledgeBase.documents.createFromFile({
file,
});
if (response.id) {
knowledgeBase.push({
id: response.id,
type: "file",
name: file.name,
});
}
}
}
// Append all urls
for (const url of urls) {
const response = await elevenlabs.conversationalAi.knowledgeBase.documents.createFromUrl({
url: url as string,
});
if (response.id) {
knowledgeBase.push({
id: response.id,
type: "url",
name: `url for ${conversationId}`,
});
}
}
// Store knowledge base IDs and conversation ID in database.
const redisRes = await redis.set(
conversationId as string,
JSON.stringify({ email, knowledgeBase })
);
console.log({ redisRes });
});
redirect("/success");
}

Verarbeitung des Post-Call-Webhooks

Der Post-Call-Webhook wird ausgelöst, wenn ein Anruf endet und die Schritte zur Analyse und Datenextraktion abgeschlossen sind.

Hier passieren mehrere Schritte:

  1. Webhook-Secret verifizieren und Webhook-Payload erstellen.
  2. Ein individuelles Stimmendesign basierend auf voice_description erstellen.
  3. Einen ElevenLabs-Agent für die Nutzer basierend auf ihrer angegebenen agent_description erstellen.
  4. Die Wissensdatenbankdokumente aus dem in Redis gespeicherten Konversationsstatus abrufen und die Wissensdatenbank an den Agent anhängen.
  5. Dem Nutzer eine E-Mail senden, um ihn darüber zu informieren, dass sein individueller ElevenLabs-Agent bereit zum Chatten ist.
./app/api/convai-webhook/route.ts
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { Redis } from "@upstash/redis";
import crypto from "crypto";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { Resend } from "resend";
import { EmailTemplate } from "@/components/email/post-call-webhook-email";
// Initialize Redis
const redis = Redis.fromEnv();
// Initialize Resend
const resend = new Resend(process.env.RESEND_API_KEY);
const elevenlabs = new ElevenLabsClient({
apiKey: process.env.ELEVENLABS_API_KEY,
});
export async function GET() {
return NextResponse.json({ status: "webhook listening" }, { status: 200 });
}
export async function POST(req: NextRequest) {
const secret = process.env.ELEVENLABS_CONVAI_WEBHOOK_SECRET; // Add this to your env variables
const { event, error } = await constructWebhookEvent(req, secret);
if (error) {
return NextResponse.json({ error: error }, { status: 401 });
}
if (event.type === "post_call_transcription") {
const { conversation_id, analysis, agent_id } = event.data;
if (
agent_id === process.env.ELEVENLABS_AGENT_ID &&
analysis.evaluation_criteria_results.all_data_provided?.result === "success" &&
analysis.data_collection_results.voice_description?.value
) {
try {
// Design the voice
const voicePreview = await elevenlabs.textToVoice.createPreviews({
voiceDescription: analysis.data_collection_results.voice_description.value,
text: "The night air carried whispers of betrayal, thick as London fog. I adjusted my cufflinks - after all, even spies must maintain appearances, especially when the game is afoot.",
});
const voice = await elevenlabs.textToVoice.createVoiceFromPreview({
voiceName: `voice-${conversation_id}`,
voiceDescription: `Voice for ${conversation_id}`,
generatedVoiceId: voicePreview.previews[0].generatedVoiceId,
});
// Get the knowledge base from redis
const redisRes = await getRedisDataWithRetry(conversation_id);
if (!redisRes) throw new Error("Conversation data not found!");
// Handle agent creation
const agent = await elevenlabs.conversationalAi.agents.create({
name: `Agent for ${conversation_id}`,
conversationConfig: {
tts: { voiceId: voice.voiceId },
agent: {
prompt: {
prompt:
analysis.data_collection_results.agent_description?.value ??
"You are a helpful assistant.",
knowledgeBase: redisRes.knowledgeBase,
},
firstMessage: "Hello, how can I help you today?",
},
},
});
console.log("Agent created", { agent: agent.agentId });
// Send email to user
console.log("Sending email to", redisRes.email);
await resend.emails.send({
from: process.env.RESEND_FROM_EMAIL!,
to: redisRes.email,
subject: "Your ElevenLabs agent is ready to chat!",
react: EmailTemplate({ agentId: agent.agentId }),
});
} catch (error) {
console.error(error);
return NextResponse.json({ error }, { status: 500 });
}
}
}
return NextResponse.json({ received: true }, { status: 200 });
}
const constructWebhookEvent = async (req: NextRequest, secret?: string) => {
const body = await req.text();
const signatureHeader = req.headers.get("ElevenLabs-Signature");
return await elevenlabs.webhooks.constructEvent(body, signatureHeader, secret);
};
async function getRedisDataWithRetry(
conversationId: string,
maxRetries = 5
): Promise<{
email: string;
knowledgeBase: Array<{
id: string;
type: "file" | "url";
name: string;
}>;
} | null> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const data = await redis.get(conversationId);
return data as any;
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`Redis get attempt ${attempt} failed, retrying...`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
return null;
}

Gehen wir jeden Schritt im Detail durch.

Webhook-Secret verifizieren und Webhook-Payload erstellen

Wenn die Webhook-Anfrage eingeht, verifizieren wir zuerst das Webhook-Secret und erstellen die Webhook-Payload.

./app/api/convai-webhook/route.ts
// ...
export async function POST(req: NextRequest) {
const secret = process.env.ELEVENLABS_CONVAI_WEBHOOK_SECRET;
const { event, error } = await constructWebhookEvent(req, secret);
// ...
}
// ...
const constructWebhookEvent = async (req: NextRequest, secret?: string) => {
const body = await req.text();
const signatureHeader = req.headers.get("ElevenLabs-Signature");
return await elevenlabs.webhooks.constructEvent(body, signatureHeader, secret);
};
async function getRedisDataWithRetry(
conversationId: string,
maxRetries = 5
): Promise<{
email: string;
knowledgeBase: Array<{
id: string;
type: "file" | "url";
name: string;
}>;
} | null> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const data = await redis.get(conversationId);
return data as any;
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`Redis get attempt ${attempt} failed, retrying...`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
return null;
}

Individuelles Stimmendesign basierend auf voice_description erstellen

Mithilfe der voice_description aus der Webhook-Payload erstellen wir ein individuelles Stimmendesign.

./app/api/convai-webhook/route.ts
// ...
// Design the voice
const voicePreview = await elevenlabs.textToVoice.createPreviews({
voiceDescription: analysis.data_collection_results.voice_description.value,
text: "The night air carried whispers of betrayal, thick as London fog. I adjusted my cufflinks - after all, even spies must maintain appearances, especially when the game is afoot.",
});
const voice = await elevenlabs.textToVoice.createVoiceFromPreview({
voiceName: `voice-${conversation_id}`,
voiceDescription: `Voice for ${conversation_id}`,
generatedVoiceId: voicePreview.previews[0].generatedVoiceId,
});
// ...

Wissensdatenbankdokumente aus dem in Redis gespeicherten Konversationsstatus abrufen

Das Hochladen der Dokumente kann länger dauern als die Analyse der Webhook-Daten. Daher müssen wir den Konversationsstatus in Redis abfragen, bis die Dokumente hochgeladen wurden.

./app/api/convai-webhook/route.ts
// ...
// Get the knowledge base from redis
const redisRes = await getRedisDataWithRetry(conversation_id);
if (!redisRes) throw new Error("Conversation data not found!");
// ...
async function getRedisDataWithRetry(
conversationId: string,
maxRetries = 5
): Promise<{
email: string;
knowledgeBase: Array<{
id: string;
type: "file" | "url";
name: string;
}>;
} | null> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const data = await redis.get(conversationId);
return data as any;
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`Redis get attempt ${attempt} failed, retrying...`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
return null;
}

Einen ElevenLabs-Agent für die Nutzer basierend auf ihrer angegebenen agent_description erstellen

Erstellen Sie den ElevenLabs-Agent für den Nutzer basierend auf seiner angegebenen agent_description und hängen Sie das neu erstellte Stimmendesign sowie die Wissensdatenbank an den Agent an.

./app/api/convai-webhook/route.ts
// ...
// Handle agent creation
const agent = await elevenlabs.conversationalAi.agents.create({
name: `Agent for ${conversationId}`,
conversationConfig: {
tts: { voiceId: voice.voiceId },
agent: {
prompt: {
prompt:
analysis.data_collection_results.agent_description?.value ??
"You are a helpful assistant.",
knowledgeBase: redisRes.knowledgeBase,
},
firstMessage: "Hello, how can I help you today?",
},
},
});
console.log("Agent created", { agent: agent.agentId });
// ...

Dem Nutzer eine E-Mail senden, um ihn darüber zu informieren, dass sein individueller ElevenLabs-Agent bereit zum Chatten ist

Sobald der Agent erstellt wurde, können Sie dem Nutzer eine E-Mail senden, um ihn darüber zu informieren, dass sein individueller ElevenLabs-Agent bereit zum Chatten ist.

./app/api/convai-webhook/route.ts
import { Resend } from "resend";
import { EmailTemplate } from "@/components/email/post-call-webhook-email";
// ...
// Send email to user
console.log("Sending email to", redisRes.email);
await resend.emails.send({
from: process.env.RESEND_FROM_EMAIL!,
to: redisRes.email,
subject: "Your ElevenLabs agent is ready to chat!",
react: EmailTemplate({ agentId: agent.agentId }),
});
// ...

Sie können new.email verwenden, ein praktisches Tool des Resend-Teams, um Ihre E-Mail-Vorlagen per Vibe Design zu erstellen. Wenn Sie mit der Vorlage zufrieden sind, erstellen Sie eine neue Komponente und fügen Sie die Agent-ID als Prop hinzu.

./components/email/post-call-webhook-email.tsx
import {
Body,
Button,
Container,
Head,
Html,
Section,
Text,
Tailwind,
} from "@react-email/components";
import * as React from "react";
const EmailTemplate = (props: any) => {
const { agentId } = props;
return (
<Html>
<Head />
<Tailwind>
<Body className="bg-[#151516] font-sans">
<Container className="mx-auto my-[40px] max-w-[600px] rounded-[8px] bg-[#0a1929] p-[20px]">
{/* Top Section */}
<Section className="mb-[32px] mt-[32px] text-center">
<Text className="m-0 text-[28px] font-bold text-[#9c27b0]">
Your ElevenLabs agent is ready to chat!
</Text>
</Section>
{/* Content Area with Icon */}
<Section className="mb-[32px] text-center">
{/* Circle Icon with Checkmark */}
<div className="mx-auto mb-[24px] flex h-[80px] w-[80px] items-center justify-center rounded-full bg-gradient-to-r from-[#9c27b0] to-[#3f51b5]">
<div className="text-[40px] text-white">✓</div>
</div>
{/* Descriptive Text */}
<Text className="mb-[24px] text-[18px] text-white">
Your ElevenLabs agent is ready to chat!
</Text>
</Section>
{/* Call to Action Button */}
<Section className="mb-[32px] text-center">
<Button
href={`https://elevenlabs.io/app/talk-to?agent_id=${agentId}`}
className="box-border rounded-[8px] bg-[#9c27b0] px-[40px] py-[20px] text-[24px] font-bold text-white no-underline"
>
Chat now!
</Button>
</Section>
{/* Footer */}
<Section className="mt-[40px] border-t border-[#2d3748] pt-[20px] text-center">
<Text className="m-0 text-[14px] text-white">
Powered by{" "}
<a
href="https://elevenlabs.io/conversational-ai"
target="_blank"
rel="noopener noreferrer"
className="underline transition-colors hover:text-gray-400"
>
ElevenLabs Agents
</a>
</Text>
</Section>
</Container>
</Body>
</Tailwind>
</Html>
);
};
export { EmailTemplate };

App ausführen

Um die App lokal vollständig auszuführen, müssen Sie zuerst den Next.js-Entwicklungsserver starten und dann in einem separaten Terminal den ngrok-Tunnel ausführen, um den Webhook-Handler im Internet verfügbar zu machen.

  • Terminal 1:
    • Führen Sie pnpm dev aus, um den Next.js-Entwicklungsserver zu starten.
pnpm dev
  • Terminal 2:
    • Führen Sie ngrok http 3000 aus, um den Webhook-Handler im Internet verfügbar zu machen.
ngrok http 3000

Öffnen Sie jetzt http://localhost:3000 und beginnen Sie mit dem Design Ihres individuellen ElevenLabs-Agent – mit Ihrer Stimme.

Nächste Schritte