Die API arbeitet mit denselben Agents, Anrufen und Credits wie das Web-Dashboard. Alles, was Sie im Dashboard erstellen, lässt sich aus Ihren eigenen Systemen steuern, und umgekehrt.
| Was | Endpunkt |
|---|---|
| Agents auflisten | GET /api/v1/voice/agents |
| Agent erstellen | POST /api/v1/voice/agents |
| Agent abrufen / ändern | GET · PATCH /api/v1/voice/agents/{id} |
| Ausgehenden Anruf tätigen | POST /api/v1/voice/calls |
| Anrufe auflisten | GET /api/v1/voice/calls |
| Anruf abrufen (Transkript) | GET /api/v1/voice/calls/{id} |
| Anruf löschen | DELETE /api/v1/voice/calls/{id} |
| Anrufe eines Anrufers löschen | POST /api/v1/voice/calls/delete-by-caller |
| Kampagnen | GET · POST /api/v1/voice/campaigns |
| Kampagne abrufen | GET /api/v1/voice/campaigns/{id} |
| Starten / pausieren / abbrechen | POST /api/v1/voice/campaigns/{id}/{action} |
| Geklonte Stimmen | GET · POST /api/v1/voice/voices |
| Geklonte Stimme löschen | DELETE /api/v1/voice/voices/{id} |
| Sperrliste | GET · POST /api/v1/voice/do-not-call |
| Von der Liste entfernen | DELETE /api/v1/voice/do-not-call/{phone} |
| Sprachen, Stimmen, Vorlagen | GET /api/v1/voice/catalog |
| Tests eines Agents | GET · POST /api/v1/voice/agents/{id}/tests |
| Tests ausführen / Lauf lesen | POST /api/v1/voice/agents/{id}/test-runs · GET /api/v1/voice/test-runs/{id} |
| Nummer einem Agent zuweisen | PATCH /api/v1/voice/phone-numbers/{id} |
| Wortlisten | GET · POST /api/v1/voice/vocabularies |
Erstellen Sie im Dashboard unter Integrationen → API-Schlüssel einen Schlüssel (oder mit einem Klick in der Übersicht) und senden Sie ihn als Bearer-Token:
Authorization: Bearer sk-your-key
Ein Schlüssel handelt in dem Workspace, in dem sein Inhaber arbeitet, mit dessen Rolle: Der Schlüssel eines Mitglieds mit Lesezugriff kann lesen, aber nichts ändern.
Erstellen Sie einen Agent aus einer Vorlage und setzen Sie auf Wunsch im selben Request seine Felder. Ohne template beginnt er leer; GET /api/v1/voice/catalog listet die Vorlagen sowie die Sprachen und Stimmen, die ein Agent annimmt. Vorlagen gibt es auf Englisch und Chinesisch; senden Sie für eine andere Sprache system_prompt und first_message in dieser Sprache. Entweder wird der ganze Request gespeichert oder kein Agent angelegt, sodass ein abgelehnter Request nach der Korrektur erneut gesendet werden kann. dashboard_url in der Antwort ist die Seite des Agents im Dashboard, auf der Sie im Browser mit dem Entwurf sprechen können. Jeder Agent läuft mit EvaSay ASR, EvaSay LLM und EvaSay TTS, die EvaSay für Sprache und Last jedes Anrufs wählt und die im Anrufpreis enthalten sind; Konten anderer Anbieter müssen nicht eingerichtet werden.
curl https://evasay.com/api/v1/voice/agents \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Front desk",
"language": "en",
"first_message": "Hi, thanks for calling Sunrise Salon. How can I help?",
"system_prompt": "You are the front desk of Sunrise Salon..."
}'
Diese Felder ändern Sie mit PATCH /api/v1/voice/agents/{id}:
| Feld | Hinweise |
|---|---|
name, first_message, system_prompt | Text |
status | published veröffentlicht den Entwurf als neue Version; draft nimmt keine Anrufe mehr an |
language | Eine von 27 Sprachen, z. B. en, zh, es, de, oder multi, um dem Anrufer zu folgen |
temperature | 0-100 |
max_duration_sec, silence_timeout_sec | Anrufgrenzen |
interruptible, end_call_enabled | Boolesche Werte |
confirm_details | Boolean; Nummern und Namen wiederholen und bestätigen lassen |
ai_disclosure | Boolean, Standard true; vor seiner ersten Nachricht sagt der Agent in der Anrufsprache, dass der Anrufer mit einer KI spricht (entfällt, wenn die erste Nachricht das schon sagt) |
voicemail_detection | Boolean; ausgehende Anrufe hören zuerst zu und enden bei einer Mailbox |
voicemail_message | Wird auf der Mailbox hinterlassen, kann {{variables}} enthalten; leer, um aufzulegen |
transfer_number | Weiterleitungsnummer, internationales Format |
transfer_destinations | Bis zu 9 weitere Nummern, [{name, number, when}]; der Agent wählt anhand von when |
transfer_briefing | Boolean; wer abnimmt, hört zuerst die Zusammenfassung des Anrufs vom Agent |
pronunciations | Bis zu 100 [{word, say, case_sensitive}]; die Stimme sagt say für word |
idle_messages | Bis zu 3 Erinnerungen, die einem schweigenden Anrufer nacheinander gesagt werden, bevor der Anruf endet |
noise_reduction | Boolean; die Hintergrundgeräusche des Anrufers werden gefiltert, bevor er verstanden wird |
recording_enabled | Boolean; Anrufe werden zweikanalig aufgenommen (Anrufer links, Agent rechts) |
recording_consent | announce, ask (nur behalten, wenn der Anrufer zustimmt) oder none |
recording_notice | Der Hinweis oder die Frage, die zuerst gesagt wird; leer für den integrierten Text in der Anrufsprache |
handoffs | Bis zu 5 [{agent_id, when}]: andere Agents, an die dieser einen Anruf übergeben darf |
knowledge_base_id | Eine Ihrer Wissensdatenbanken |
vocabulary_id | Eines Ihrer Vokabulare; Anrufer, die dessen Begriffe sagen, werden zuverlässiger verstanden |
voice_id | Eine integrierte EvaSay-Stimmen-ID oder eine Ihrer geklonten Stimmen (clone:…) |
Integrierte Stimmen hängen von der Sprache ab: Chinesisch hat ming-designed-female-clear, ming-designed-female-warm (weiblich), ming-designed-male-clear und ming-designed-male-friendly (männlich), die anderen Sprachen F1–F5 (weiblich) und M1–M5 (männlich). Eine integrierte Stimme, die die Sprache des Agents nicht spricht, wird durch die Stimme desselben Geschlechts ersetzt, die sie spricht. Der ältere Feldname tts_voice_id wird weiterhin akzeptiert. Jeder andere Wert für voice_id und jede noch nicht fertige geklonte Stimme wird abgelehnt.
analysis_config legt fest, was nach jedem Anruf ausgewertet wird: summary (Standard true), summaryLanguage, successCriteria (was ein erfolgreicher Anruf erreicht), fields (bis zu 20 {name, type, description} zum Extrahieren, type ist string, number oder boolean) und scorecard (bis zu 10 {name, description, weight}, Gewicht 1–5). Die Ergebnisse stehen in analysis des Anrufs und im Webhook call.analyzed.
Wenn Sie die Felder eines Agents ändern, ändern Sie seinen Entwurf. Anrufe nutzen weiter die veröffentlichte Version, bis Sie den Entwurf mit POST /api/v1/voice/agents/{id}/publish (optional mit note) veröffentlichen oder status: "published" im selben PATCH setzen. Jede Veröffentlichung speichert eine nummerierte Version; published_version im Agent zeigt, welche Anrufe nutzen. Ein Anruf bleibt bei der Version, die bei seinem Beginn aktiv war, sodass eine Veröffentlichung während des Anrufs ihn nicht ändert. Testanrufe aus dem Dashboard nutzen den Entwurf.
GET /agents/{id}/versions listet die Versionen, und POST /agents/{id}/versions/{version}/restore setzt zurück: Neue Anrufe nutzen diese Version, und der Entwurf wird zu ihr. Name, Bereitstellung, Widget-Aussehen und Benachrichtigungen des Agents sind nicht versioniert und ändern sich sofort, ebenso die Dokumente seiner Wissensdatenbank.
Ein Test spielt einen Anruf als Text durch: Ein simulierter Anrufer spielt scenario, der Agent antwortet aus seinem Entwurf (Anweisungen, erste Nachricht und Wissen), und ein Prüfer bewertet das Gespräch anhand von success_criteria. Schreiben Sie Tests für die wichtigen Anrufe, führen Sie sie nach jeder Änderung aus und veröffentlichen Sie, wenn sie bestehen.
curl https://evasay.com/api/v1/voice/agents/AGENT_ID/tests \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Move a booking",
"scenario": "A regular customer wants to move Friday 3 pm to Saturday morning.",
"success_criteria": "Offers Saturday times and confirms the new time and the customer'"'"'s name.",
"max_turns": 8
}'
POST /agents/{id}/test-runs führt alle Tests des Agents aus, oder die in test_ids, und antwortet mit je einem Lauf (status: "running"). Fragen Sie GET /test-runs/{id} ab, bis status passed, failed oder error ist; dann enthält der Lauf das transcript und den reason des Prüfers (auf Englisch, oder auf Chinesisch mit reason_language: "zh"). Jeder Lauf kostet Credits, die bei den Tests im Dashboard angezeigt werden; die Läufe stoppen beim ersten, den das Guthaben nicht bezahlen kann, und not_started listet die übrigen. Ein Lauf, der nicht durchläuft, wird erstattet. Tests prüfen, was der Agent sagt, nicht seine Stimme oder sein Timing, und rufen seine Funktionen nicht auf: Diese prüfen Sie vorab mit POST /tools/{id}/test. Ein Agent hat bis zu 30 Tests; PATCH und DELETE /agents/{id}/tests/{test_id} ändern oder entfernen einen.
Neben ganzen Anrufen (type: "simulation", Standard) kann ein Test eine einzelne Antwort prüfen. type: "next_reply" nimmt chat_history, das Gespräch davor, das mit dem Anrufer endet ([{role, text}], role ist caller oder agent), und success_criteria für die nächste Antwort des Agents. type: "tool_call" nimmt chat_history und expected_tool {name, arguments, match}: Der Agent soll name aufrufen (eine seiner Funktionen oder end_call, transfer_call, handoff_to_agent), mit arguments, genau verglichen (Text getrimmt, ohne Groß-/Kleinschreibung) oder mit match: "judge" nach Bedeutung; weitere übergebene Argumente werden ignoriert. Das transcript eines Laufs zeigt die aufgerufenen Funktionen in tool_calls.
POST /agents/{id}/tests/generate entwirft Tests aus dem Entwurf des Agents: seinen Anweisungen, seinem Wissen und seinen Funktionen. Es nimmt count (1–10, Standard 5), types, focus (was abgedeckt werden soll) und language (en oder zh, für Namen und Kriterien), kostet Credits wie ein Lauf und antwortet mit Entwürfen, die Sie prüfen und an POST /agents/{id}/tests senden; mit save: true werden sie gespeichert.
hooks tut zu einem Zeitpunkt des Anrufs etwas, bis zu 10 Regeln: on: "silence" (der Anrufer hat seit dem Ende des Agents seconds lang nichts gesagt, 3–600; einmal, bis er wieder spricht), on: "time_elapsed" (seconds nach Anrufbeginn, 10–3600) oder on: "call_ending". Jede führt per do bis zu 3 von {type: "say", text}, {type: "transfer", destination?}, {type: "end_call", text?} und {type: "tool", name, args?} aus; eine Regel für das Anrufende führt nur Funktionen aus. Ein Anruf, den eine Regel beendet, hat ended_reason rule_ended.
Bei Telefonanrufen erreichen die Tasten, die ein Anrufer drückt, den Agent als Antwort: Eine Eingabe endet mit # oder einer Pause von zwei Sekunden. Bei ausgehenden Anrufen kann der Agent auch Tasten drücken, um durch das Telefonmenü eines Unternehmens zu kommen.
transfer_number ist die Hauptnummer des Agents, um einen Anrufer an eine Person zu übergeben, und die Nummer, die angerufen wird, wenn der Workspace keine Credits mehr hat. transfer_destinations fügt benannte Nummern hinzu, jeweils mit einem Hinweis, wann sie zu nutzen sind („Abrechnung: Fragen zu Rechnungen und Erstattungen“), und der Agent wählt. Mit transfer_briefing schreibt der Agent beim Weiterleiten eine kurze Zusammenfassung; wer abnimmt, hört sie mit einer EvaSay-Stimme und in der Zusammenfassungssprache des Agents, bevor der Anrufer durchgestellt wird. Der ended_reason des Anrufs ist dann transferred.
Mit handoffs kann ein Agent einen Anruf an einen anderen veröffentlichten Agent Ihres Workspace übergeben, etwa ein Empfang, der eine Buchung an einen Buchungs-Agent gibt. Der Agent wählt anhand von when. Der andere Agent übernimmt denselben Anruf mit allem bisher Gesagten und spricht mit seinen eigenen Anweisungen, seiner Stimme, seinem Wissen, seinen Tools und Übergaben. Der Anruf wird weiter unter dem ersten Agent gelistet, analysiert und abgerechnet; sein Transkript vermerkt jede Übergabe.
Nummern werden im Dashboard mit Ihrem eigenen Carrier-Konto verbunden. GET /api/v1/voice/phone-numbers listet sie, und PATCH /api/v1/voice/phone-numbers/{id} mit { "agent_id": "AGENT_ID" } leitet die Anrufe der Nummer an einen Agent (seine veröffentlichte Version), mit "agent_id": null an keinen; label benennt sie um.
Eine Wortliste enthält Namen und Begriffe, die Anrufer sagen und die eine Spracherkennung sonst falsch verstehen würde, etwa Produkt-, Medikamenten- oder Straßennamen. POST /api/v1/voice/vocabularies mit { "name": "Products", "terms": ["Lumora", "Vantix Pro"] } (bis zu 1.000 Begriffe mit je 50 Zeichen, oder "preset": "medical" bzw. "legal" als Ausgangspunkt), dann setzen Sie vocabulary_id des Agents. GET, PATCH (name, terms) und DELETE /vocabularies/{id}; eine Liste, die ein Agent nutzt, kann nicht gelöscht werden.
Jede Nummer hat auf der Seite Telefonnummern Anrufregeln, die gelten, bevor der Agent antwortet: Gesperrte Nummern oder Nummernanfänge (+1555) und Anrufer mit unterdrückter Nummer werden unbeantwortet abgewiesen und kosten nichts; bestimmte Anrufer können direkt an eine andere Nummer durchgestellt werden; und wenn der Agent nicht antworten kann (nicht veröffentlicht, kein Worker, keine Credits ohne Weiterleitungsnummer), kann der Anruf eine Nummer anrufen oder Ihre eigene Nachricht hören. Eine Startabfrage (run_at_start) kann einen Anrufer ebenfalls abweisen, indem sie {"reject": true, "message": "..."} antwortet: Der Agent sagt die Nachricht, falls vorhanden, und legt auf, mit ended_reason rejected.
Tätigen Sie einen Anruf von einer der Telefonnummern Ihres Workspace. Jeder Request braucht einen eindeutigen Idempotency-Key; wird derselbe Schlüssel erneut gesendet, kommt derselbe Anruf zurück, statt doppelt zu wählen.
curl https://evasay.com/api/v1/voice/calls \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "AGENT_ID",
"to": "+14155550100",
"variables": { "customer_name": "Alex", "order_id": "1234" }
}'
from ist erforderlich, wenn der Workspace mehr als eine Telefonnummer hat. variables füllen Platzhalter wie {{customer_name}} in der ersten Nachricht und im Prompt des Agents.
GET /api/v1/voice/calls/{id} liefert Status, Dauer, berechnete Credits, Zusammenfassung, Analyse und Transkript des Anrufs. Anrufe listen Sie mit GET /api/v1/voice/calls?agent_id=&status=&channel=&user_id=&page= (user_id: Ihre eigene ID für die Person, aus einem Web-Anruf-Token). Seine turns sind das Debug-Protokoll des Anrufs pro Wechsel: wohin die Zeit ging, vom Ende des Anrufers bis zum Hören der Antwort, in Millisekunden — waitMs (Sprechende), sttMs (Erkennung), llmMs (erstes Wort des Modells, eins mehr pro Runde mit Funktionen), ttsMs (erster Ton der Stimme), firstAudioMs (Antwort gehört) — mit den aufgerufenen Funktionen, Unterbrechungen und Fehlern. Die Anrufseite zeigt es ebenfalls.
Mit recording_enabled wird jeder Anruf als zweikanalige WAV aufgenommen: der Anrufer links, der Agent rechts, mit der Abtastrate des Anrufs. Mit recording_consent: "announce" sagt der Agent zuerst, dass der Anruf aufgenommen wird; mit "ask" fragt er, und die Aufnahme wird nur behalten, wenn der Anrufer zustimmt (keine Antwort zählt als Nein); mit "none" wird nichts gesagt. Prüfen Sie, was das Recht dort verlangt, wo Sie und Ihre Anrufer sind.
Aufnahmen werden im Speicher von EvaSay gehalten oder in Ihrem eigenen S3-kompatiblen Bucket (AWS S3, Cloudflare R2, Google Cloud Storage, Supabase, MinIO), festgelegt unter Integrationen → Webhooks & Benachrichtigungen → Speicher für Aufnahmen. Der Worker, der den Anruf ausführt, lädt die Datei direkt in den Bucket. GET /api/v1/voice/calls/{id} liefert eine eine Stunde gültige recordingUrl, sobald die Aufnahme gespeichert ist, und recording.status (recording, stored, declined oder failed).
DELETE /api/v1/voice/calls/{id} löscht einen beendeten Anruf mit Transkript, Aufnahme (im Speicher von EvaSay oder in Ihrem eigenen Bucket), Analyse und Webhook-Zustellungen. Die verbrauchten Credits bleiben im Credit-Verlauf. Ein Anruf, der noch nicht gelöscht werden kann, antwortet mit 409 und code call_not_deletable_yet: Er läuft noch oder ist gerade erst beendet, wird noch abgerechnet, seine Aufnahme wird möglicherweise noch hochgeladen, oder er hat offene Credits, die Ihr Guthaben nicht gedeckt hat (laden Sie zuerst Credits auf).
Verlangt eine Person die Löschung ihrer Daten, löscht POST /api/v1/voice/calls/delete-by-caller mit { "phone_number": "+14155550123" } alle Anrufe mit dieser Nummer (bei eingehenden Anrufen die des Anrufers, bei ausgehenden die angerufene Nummer) oder mit { "user_id": "..." } alle Web-Anrufe, deren Token diese user_id enthielt. Die Antwort ist { "deleted": 12, "kept_back": { "settling": 1 }, "more": false }: höchstens 200 Anrufe pro Anfrage, fragen Sie also erneut, solange more true ist, und später noch einmal für die Anrufe in kept_back. Steht die Nummer auf Ihrer Sperrliste, bleibt sie dort. Im Dashboard geht dasselbe unter Anrufe → Daten eines Anrufers löschen.
Senden Sie POST /api/v1/voice/calls/{id}/control, während ein Anruf läuft. Der Worker, der den Anruf ausführt, übernimmt den Befehl innerhalb von etwa 2 Sekunden; die API antwortet 202. Ist der Worker, der den Anruf ausführt, nicht erreichbar, antwortet die API 503 (code call_unreachable), und der Befehl wird nicht ausgeführt.
type | Was passiert |
|---|---|
say | Der Agent sagt text nach seinem aktuellen Satz, oder sofort mit "interrupt": true |
note | Dem Agent wird text mitgeteilt (nicht gesprochen), und er berücksichtigt es ab seiner nächsten Antwort; das Transkript vermerkt es |
end | Der Agent sagt text, falls angegeben, und legt dann auf; ein Telefonanruf ohne text wird sofort beendet |
Der ended_reason des Anrufs ist dann api_ended. Die Anrufseite im Dashboard hat dieselben Steuerungen.
POST /api/v1/voice/calls/{id}/listen (optional { "channels": 2 }) liefert eine listen_url, die Sie innerhalb von zwei Minuten öffnen können. Es ist ein WebSocket: zuerst eine JSON-Nachricht {"type":"start","sampleRate":8000,"channels":1,"encoding":"pcm_s16le"}, dann Binärframes mit 16-Bit-Little-Endian-PCM mit dem, was der Anrufer hört (beide Stimmen gemischt; mit channels: 2 der Anrufer links und der Agent rechts). Er schließt, wenn der Anruf endet. Das Audio kommt direkt vom Worker, der den Anruf ausführt, nicht über die Steuerungsebene von EvaSay; der Mithören-Button auf der Anrufseite des Dashboards nutzt dieselbe Adresse.
Senden und empfangen Sie das Audio eines Anrufs aus Ihrem eigenen Programm, etwa Ihrer eigenen Telefonanlage oder App. Starten Sie den Anruf:
curl https://evasay.com/api/v1/voice/calls/websocket \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "AGENT_ID", "encoding": "pcm_s16le", "sample_rate": 16000 }'
Die websocket_url in der Antwort enthält ein Einmal-Token und kann innerhalb von 15 Minuten geöffnet werden. encoding ist pcm_s16le (16-Bit-Little-Endian-PCM mit einer sample_rate von 8000, 16000 oder 24000) oder mulaw (8 kHz μ-law). Audio fließt in beide Richtungen als Binärframes in diesem Format, idealerweise je 20 ms. Textframes sind JSON:
| Richtung | Nachrichten |
|---|---|
| Sie → EvaSay | {"type":"dtmf","digits":"12#"} Tastendrücke; {"type":"end"} legt auf; {"type":"text","text":"…"} vom Anrufer getippte Worte ("input":"button" für eine angetippte Antwort); {"type":"context","text":"…","key":"cart"} was Ihre App meldet (der Agent antwortet nicht darauf); {"type":"tool_result","id":"…","result":{…}} (oder "error") die Antwort einer Seitenfunktion |
| EvaSay → Sie | start (mit callId); clear (der Anrufer hat unterbrochen: noch nicht abgespieltes Agent-Audio verwerfen); transcript (role, text, final und input für getippte Worte); user_started_speaking, user_stopped_speaking, agent_started_speaking, agent_stopped_speaking; cards (cards, quick_replies); tool (id, name, arguments: eine Ihrer Seitenfunktionen ausführen); notice (code: too_fast oder limit für getippte Worte); ended (mit reason, danach schließt der Socket) |
Der Agent grüßt, sobald Sie verbinden. user_id und page_tools (die Seitenfunktionen, die Ihre App beantwortet, siehe unten) können dem Request hinzugefügt werden. Anrufe werden wie alle anderen pro Minute abgerechnet, mit denselben Anrufprotokollen, Analysen und Webhooks.
Bei einem Web-Anruf (Widget, gehostete Seite, Ihre App) sieht der Anrufer neben der Stimme einen Chat, sodass der Agent mehr kann als sprechen. Telefonanrufer bekommen nichts davon.
Aktivieren Sie Agent → Wissen & Tools → An den Anrufer senden (send_to_caller in der Agent-API), und der Agent kann bis zu fünf Karten gleichzeitig auf dem Bildschirm des Anrufers zeigen: je einen Titel, eine Zeile darunter, eine Beschreibung, ein Bild, einen Link und bis zu zwei Antwort-Buttons; er kann auch bis zu drei Schnellantworten unter einer Frage anbieten. Links werden nie vorgelesen.
Der Agent darf nur Links und Bilder senden, die er in diesem Anruf bekommen hat: aus seinen Anweisungen und seiner Begrüßung, der Wissensdatenbank (ein von einer Webseite gelesenes Dokument trägt deren Adresse), den Antworten Ihrer Funktionen und den vorgefertigten Karten. Ein Link muss außerdem auf einem der allowed_hosts liegen (die Website einer vorgefertigten Karte ist es immer). Links, die der Agent erfindet oder die der Anrufer vorliest, werden nicht gesendet. Links auf diesen Websites in den Worten des Agents sind im Chat anklickbar.
"send_to_caller": {
"enabled": true,
"allowed_hosts": ["shop.example.com", "*.cdn.example.com"],
"presets": [
{ "name": "hours", "when": "asked when we open", "title": "Opening hours",
"description": "Mon–Sat 9:00–18:00", "url": "https://shop.example.com/stores", "image_url": "" }
]
}
Jede Sendung erhalten Sie als Webhook call.message_sent (channel, items mit title und url, quickReplies, blocked). Ein Anruf sendet höchstens 10 Mal.
Während des Anrufs kann der Anrufer auch tippen (eine E-Mail-Adresse, eine Bestellnummer) oder einen Antwort-Button antippen; der Agent antwortet darauf wie auf Gesprochenes und hört zuerst auf, falls er gerade spricht. Bis zu 500 Zeichen pro Nachricht, eine pro Sekunde, 100 pro Anruf. Im Anrufprotokoll sind diese Wechsel als getippt oder angetippt markiert.
Das Widget gibt Ihrer Seite ein evasay-Objekt. Alles ist optional, und der Anrufrahmen hört nur auf Ihre Seite, wenn sie eine der erlaubten Websites des Widgets ist (Agent → Bereitstellen):
<script src="https://evasay.com/voice-widget.js" data-agent="AGENT_SLUG" async></script>
<script>
window.evasay = window.evasay || [];
evasay.push(function (agent) {
agent.setVariables({ plan: 'pro', page: location.pathname }); // für den nächsten Anruf
agent.update('Cart: 2 items, $120', { key: 'cart' }); // während des Anrufs
agent.registerTool('add_to_cart', async function (args) {
// Ihr Code, im Browser des Besuchers
return { ok: true, checkout: 'https://shop.example.com/checkout' };
});
agent.on('cards', function (cards) {}); // auch 'live', 'ended'
});
</script>
setVariables-Werte füllen {{name}} in Anweisungen und Begrüßung. Sie kommen aus dem Browser des Besuchers, daher wird dem Agent gesagt, dass sie nicht geprüft sind, und sie erreichen nie Ihre Funktionen oder die Startabfrage.update sagt dem Agent, was auf der Seite passiert, ohne ihn antworten zu lassen; ein neueres Update mit demselben key ersetzt das ältere."kind": "page", keine url) hinzu und registrieren Sie auf Ihrer Seite eine Funktion mit demselben Namen. Der Agent darf sie nur bei Anrufen von einer Seite aufrufen, die sie registriert hat; er wartet bis zu timeout_sec (1–10, Standard 5) auf die Antwort, außer wait_for_result ist false. Sie läuft angemeldet als der Besucher, wie ein Klick von ihm: Fragen Sie auf Ihrer eigenen Seite nach einer Bestätigung, bevor etwas Geld kostet oder nicht rückgängig zu machen ist. Links in ihrer Antwort können als Karten gesendet werden.Stellen Sie Wer einen Anruf starten kann auf Nur mit Token, und lassen Sie Ihren Server ein Einmal-Token für den angemeldeten Nutzer holen:
curl https://evasay.com/api/v1/voice/web-calls \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "AGENT_ID", "user_id": "u_42", "variables": { "name": "Ann" }, "expires_in": 600 }'
Die Antwort enthält token (ein Anruf innerhalb von expires_in Sekunden, 30–3600, Standard 600), agent (der Slug) und web_call_url. Geben Sie das Token der Seite mit data-token-url="/your/endpoint" am Skript des Widgets (es sendet dort einen POST mit den Cookies des Besuchers und liest { "token": "…" }) oder mit agent.setToken(async () => token). Die variables des Tokens sind geprüft: Anweisungen, Startabfrage und die Vorlagen Ihrer Funktionen dürfen sie nutzen, ebenso user_id, das der Anruf behält (userId im Anruf, user_id zum Filtern von Anrufen). Behalten Sie Ihren API-Schlüssel auf Ihrem Server.
In Ihrer eigenen App senden Sie { "token": "…", "pageTools": ["add_to_cart"] } per POST an https://evasay.com + web_call_url. Die Antwort ist die Verbindung des Anrufs (eine WebRTC-Offer-Adresse oder eine WebSocket-Adresse mit ihrem Anruf-Token) für einen RTVI-Client wie die Client-SDKs von Pipecat für Web, iOS, Android und React Native. Karten, Seitenfunktionen und Hinweise kommen als RTVI-server-messages (evasay.cards, evasay.tool, evasay.notice); senden Sie getippte Worte mit send-text und Seitenmeldungen und Antworten als client-messages evasay.context und evasay.tool_result. Oder übertragen Sie das Audio selbst mit Audio über einen WebSocket und übergeben Sie user_id und page_tools.
Unter Telefonnummern → SIP können Ihre eigene Telefonanlage, SIP-Telefone oder Ihr SIP-Trunk Ihre Agents direkt anrufen; Ihr SIP-Anbieter berechnet die Anrufe:
sip:ev…@<SIP-Domain von EvaSay>, nur eingehend, für Telefonanlagen (3CX, FreePBX, Asterisk …) und SIP-Telefone.from); Weiterleitungen an eine Person werden per REFER an den Trunk übergeben. Wenn der Trunk nach Zugangsdaten fragt, antwortet EvaSay mit dem eingetragenen Trunk-Benutzernamen und -Passwort.Eingehende Anrufe melden sich per Digest mit dem Benutzernamen und Passwort an, die EvaSay Ihnen gibt (der Realm ist die SIP-Domain); Sie können auch die Quell-IPs einschränken oder nur per IP akzeptieren, wenn Ihr Anbieter sich nicht anmelden kann (dann sind die IPs erforderlich). Jede SIP-Adresse und jeder Trunk hat eine Grenze für gleichzeitige Anrufe; darüber hinaus erhalten Anrufe 486. Passwörter werden einmal angezeigt, beim Erstellen oder Zurücksetzen. Nur UDP und G.711 (PCMU, PCMA); Tastendrücke per RFC 4733 oder SIP INFO; schalten Sie die Registrierung (REGISTER) am Trunk Ihrer Telefonanlage aus.
Eine Kampagne ruft eine Kontaktliste mit einem Agent an, innerhalb von Anrufzeiten und einer Parallelitätsgrenze (max_concurrency, bis zu 100 Anrufe gleichzeitig und nie mehr als die Grenze Ihres Workspace für gleichzeitige Anrufe), und versucht es erneut bei Personen, die sie nicht erreicht hat.
curl https://evasay.com/api/v1/voice/campaigns \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Appointment reminders",
"agent_id": "AGENT_ID",
"phone_number_id": "PHONE_NUMBER_ID",
"timezone": "America/New_York",
"window_start": "09:00",
"window_end": "18:00",
"max_concurrency": 2,
"max_attempts": 2,
"retry_delay_min": 60,
"consent_confirmed": true,
"contacts": [
{ "phone": "+14155550100", "name": "Alex", "appointment": "Tuesday 3 pm" }
]
}'
Kontakte können auch CSV-Text mit der Telefonnummer in der ersten Spalte sein. consent_confirmed: true ist erforderlich: Damit bestätigen Sie, dass alle auf der Liste zugestimmt haben, angerufen zu werden, auch von einer KI-Stimme, und EvaSay speichert diese Bestätigung mit der Kampagne (consent_confirmed_at). Die Kampagne wird als Entwurf erstellt; starten Sie sie mit POST /api/v1/voice/campaigns/{id}/start und nutzen Sie pause oder cancel auf dieselbe Weise. Der Agent muss veröffentlicht sein, bevor eine Kampagne startet.
Mit aktivem voicemail_detection (Standard) hört ein ausgehender Anruf, ob die Gegenseite spricht, bevor der Agent grüßt; bleibt sie still, grüßt der Agent nach zwei oder drei Sekunden. Hört der Agent eine Mailbox oder eine Ansage der Telefongesellschaft, wartet er, bis Ansage und Piepton vorbei sind, hinterlässt voicemail_message oder legt auf, wenn es keine gibt. Solche Anrufe enden mit ended_reason voicemail, werden für ihre Dauer berechnet und weder analysiert noch gemeldet.
In einer Kampagne wird eine Nummer, die eine Mailbox erreicht hat, erneut angerufen wie eine, die nicht abgenommen hat, und die Nachricht wird nur beim letzten Versuch hinterlassen, sodass niemand dieselbe Nachricht zweimal bekommt.
Jeder ausgehende Anruf, aus einer Kampagne oder über POST /api/v1/voice/calls, prüft zuerst die Sperrliste des Workspace. Eine gelistete Nummer wird nie gewählt: Die API antwortet 409 mit code do_not_call, und eine Kampagne markiert den Kontakt als canceled mit outcome do_not_call und macht mit dem nächsten weiter.
Bittet die Person bei einem vom Agent getätigten Anruf darum, nicht mehr angerufen zu werden, setzt der Agent ihre Nummer selbst auf die Liste, sagt es ihr, und der Webhook call.do_not_call wird gesendet. Nummern können auch unter Kampagnen → Sperrliste oder per API hinzugefügt und entfernt werden:
curl https://evasay.com/api/v1/voice/do-not-call \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{ "phones": ["+14155550100"], "note": "Asked by email" }'
Nummern stehen im internationalen Format; bis zu 1.000 auf einmal. GET /api/v1/voice/do-not-call listet sie, neueste zuerst (search, limit, page), jeweils mit ihrer source (call, dashboard oder api). DELETE /api/v1/voice/do-not-call/%2B14155550100 nimmt eine wieder herunter; tun Sie das nur, wenn die Person zugestimmt hat, angerufen zu werden.
POST /api/v1/voice/voices erstellt eine Stimme aus einer WAV-Aufnahme einer sprechenden Person (multipart audio, name, language, consent=true). Die Antwort ist 202 mit Status running; fragen Sie GET /api/v1/voice/voices ab, bis sie ready ist, und setzen Sie dann die voice_id eines Agents auf ihre voice_id. language ist die in der Aufnahme gesprochene Sprache, eine der obigen Agent-Sprachen; die Stimme spricht alle außer Chinesisch, wo eine integrierte Stimme desselben Geschlechts antwortet, und klingt in der Sprache der Aufnahme am ähnlichsten. Jede geklonte Stimme kostet Credits, die im Dashboard angezeigt werden, bevor Sie sie erstellen.
Fügen Sie unter Integrationen → Webhooks & Benachrichtigungen eine https-Adresse hinzu, um Anrufereignisse zu empfangen:
| Ereignis | Wann |
|---|---|
call.started | Der Agent hat abgenommen |
call.ended | Der Anruf ist beendet, mit Dauer und Credits |
call.analyzed | Zusammenfassung, Ergebnis, extrahierte Felder und Transkript sind bereit |
call.transcript | Während des Anrufs alle paar Sekunden die neuen Zeilen des Transkripts |
call.tool_called | Der Agent hat eine Ihrer Funktionen aufgerufen: name, arguments, status, durationMs |
call.handed_off | Der Anruf wurde an einen anderen Agent übergeben: fromAgentId, toAgentId |
call.transferred | Der Anruf wurde an eine Person weitergeleitet: destination |
call.voicemail | Ein ausgehender Anruf hat eine Mailbox erreicht |
call.do_not_call | Die Person bei einem ausgehenden Anruf möchte nicht mehr angerufen werden: phone |
call.recording_ready | Die zweikanalige Aufnahme ist gespeichert: recordingUrl (24 Stunden gültig), durationMs |
call.message_sent | Der Agent hat Karten auf dem Bildschirm eines Web- oder App-Anrufers gezeigt: items, quickReplies |
alert.triggered | Einer Ihrer Alarme (Webhooks & Benachrichtigungen → Alarme) hat seine Schwelle überschritten |
alert.resolved | Dieser Alarm ist wieder im Normalbereich |
Ereignisse während eines Anrufs enthalten data.call (id, agentId, channel, direction, Nummern). Jeder Request ist signiert:
EvaSay-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
EvaSay-Delivery: <delivery id>
Prüfen Sie die Signatur mit dem Webhook-Secret, das beim Erstellen des Webhooks angezeigt wurde, und antworten Sie mit einem 2xx-Status. Fehlgeschlagene Zustellungen werden nach 1 Minute, 5 Minuten, 30 Minuten, 2 Stunden und 12 Stunden mit demselben Inhalt und derselben EvaSay-Delivery-ID wiederholt, sodass Sie Wiederholungen ignorieren können. Die letzten Zustellungen eines Webhooks, mit dem genau gesendeten Inhalt und dem Status, den Ihr Endpunkt geantwortet hat, listet GET /webhooks/{id}/deliveries und das Dashboard; POST /webhooks/{id}/deliveries/{delivery_id} sendet eine erneut.
Neben E-Mail und den Webhooks alert.triggered / alert.resolved können Alarme unter Webhooks & Benachrichtigungen → Alarme → Auch senden an an einen Slack-Kanal (Incoming Webhook), einen WeCom-Gruppenroboter oder Telegram gehen.
Fehler haben eine einheitliche Form:
{
"error": {
"type": "invalid_request_error",
"code": "invalid_agent_field",
"message": "status must be draft or published",
"param": "status"
}
}
| Status | Bedeutung |
|---|---|
| 400 | Ungültige Eingabe (code und param sagen, welche) |
| 401 | Fehlender oder ungültiger API-Schlüssel |
| 402 | Nicht genug Credits, um den Anruf zu starten |
| 403 | Der Schlüssel ist nur lesend, oder der Agent ist nicht verfügbar |
| 404 | Kein solcher Agent, Anruf oder keine solche Kampagne in diesem Workspace |
| 409 | Falscher Zustand (z. B. eine laufende Kampagne starten), ein Anbieterkonto ist nicht verbunden, oder die Nummer steht auf der Sperrliste (do_not_call) |
| 429 | Zu viele Requests; langsamer werden und erneut versuchen |
Die Voice-API-Requests des Workspace der letzten 30 Tage (Zeit, Endpunkt, Status, Dauer, Schlüssel und Fehlercode; keine Inhalte) stehen unter API-Schlüssel → API-Anfrageprotokoll.
Lesezugriffe sind auf 120 Requests pro Minute und Schlüssel begrenzt, Schreibzugriffe und Anrufe auf 30.
Anrufe werden pro Minute aus den Credits des Workspace abgerechnet, demselben Guthaben, das das Dashboard nutzt. Die aktuellen Tarife stehen auf der Preisseite.
Nutzen Sie den OpenAPI-Vertrag, um einen Integrations-Client zu generieren. Öffentliche API, Dashboard und MCP-Verwaltungsendpunkt arbeiten mit denselben Workspace-Ressourcen und Berechtigungen.
| Funktion | Endpunkt |
|---|---|
| Wiederverwendbare Tools | GET / POST /api/v1/voice/tools |
| Tool lesen / ändern / löschen | GET / PATCH / DELETE /api/v1/voice/tools/{id} |
| Tool in der Vorschau ansehen oder testen | POST /api/v1/voice/tools/{id}/test |
| Tools an einen Agent binden | PUT /api/v1/voice/agents/{id}/tools |
| Wissensdatenbanken | GET / POST /api/v1/voice/knowledge-bases |
| Wissensdatenbank lesen / ändern / löschen | GET / PATCH / DELETE /api/v1/voice/knowledge-bases/{id} |
| Dokumente hinzufügen / auflisten | POST / GET /api/v1/voice/knowledge-bases/{id}/documents |
| Dokument lesen / löschen | GET / DELETE /api/v1/voice/knowledge-bases/{id}/documents/{doc_id} |
| Abonnements für Anrufereignisse | GET / POST /api/v1/voice/webhooks |
| Abonnement lesen / ändern / löschen | GET / PATCH / DELETE /api/v1/voice/webhooks/{id} |
| Signiertes Testereignis senden | POST /api/v1/voice/webhooks/{id}/test |
| Entfernte MCP-Tools finden | POST /api/v1/voice/mcp/discover |
| MCP-Verwaltungsendpunkt | /api/v1/voice/mcp |
Registrieren Sie ein HTTP-Tool, das Ihren CRM-Adapter abfragt:
{
"name": "lookup_customer",
"description": "Find a customer after confirming their customer ID.",
"kind": "http",
"url": "https://crm.example.com/customers/{{customer_id}}",
"method": "GET",
"read_only": true,
"credential_ref": "crm",
"input_schema": {
"type": "object",
"properties": { "customer_id": { "type": "string" } },
"required": ["customer_id"],
"additionalProperties": false
},
"response_path": "data"
}
POST /tools liefert { "data": { "id": "TOOL_ID", ... } }. Binden Sie seine Definition mit PUT /agents/AGENT_ID/tools und { "tool_ids": ["TOOL_ID"] } an einen Agent. Das ersetzt die gesamte Tool-Liste durch Snapshots; binden Sie neu, wenn sich ein Bibliotheks-Tool ändert. Das Löschen einer Bibliotheksdefinition lässt bestehende Snapshots bestehen. Inline-Definitionen können Sie auch über das Feld tools der Agent-API lesen und ersetzen. Nutzen Sie analysis_config und widget_config, um Analyse und Widget über die Agent-API zu konfigurieren.
Ein Tool kann GET, POST, PUT, PATCH oder DELETE nutzen. query und request_body akzeptieren verschachtelte JSON-Vorlagen wie { "customer": { "id": "{{customer_id}}" } }. Ein vollständiger Platzhalter behält den ursprünglichen JSON-Typ. URL-Platzhalter werden kodiert und dürfen nur nach einem festen öffentlichen HTTPS-Host stehen. Ohne request_body erhalten Nicht-GET-Tools { "arguments": {...}, "call": { "callId": "...", "agentId": "...", "toolCallId": "...", "idempotencyKey": "..." } }. response_path wählt ein Feld in Punktnotation. Einfache parameters werden weiterhin akzeptiert; input_schema unterstützt zusätzlich verschachtelte Objekte, Arrays, Enums und Zahlenbereiche. Externe Schema-Referenzen und reguläre Ausdrücke werden nicht akzeptiert.
static_args: Werte, die bei jedem Aufruf gesendet werden, egal was das Modell schreibt, etwa eine Filial-ID; sie füllen auch {{name}} in Adresse und Body.extract: [{name, path}] behält Felder aus der Antwort einer Funktion (data.id) für {{name}} späterer Funktionen, sodass die customer_id einer Abfrage in die folgende Bestellung gehen kann, ohne dass das Modell sie wiederholt. Die Felder einer Startabfrage werden genauso behalten.reject_when: bis zu 5 Regeln {on: caller|agent, pattern, negate}; solange alle auf die letzten Worte zutreffen, wird die Funktion nicht ausgeführt und der Agent erhält reject_message.model_says: Bei jedem Aufruf schreibt das Modell einen Satz, der gesagt wird, während die Funktion läuft, statt des festen speak_before.Verbinden Sie unter Integrationen → Webhooks & Benachrichtigungen → Verbundene Apps eine App und nutzen Sie dann „Fertige Funktion hinzufügen“ im Tab Wissen & Tools des Agents; ein eigener Endpunkt ist nicht nötig:
check_availability (freie Zeiten an einem Datum) und book_appointment (bucht die vom Anrufer gewählte Zeit) hinzu. Zeiten in Google Kalender folgen der Zeitzone, den Öffnungstagen, Zeiten und Termindauer, die Sie festlegen; Cal.com nutzt die Verfügbarkeit des Ereignistyps selbst und eine von Ihnen festgelegte Ersatz-E-Mail, wenn der Anrufer keine nennt.save_to_sheet hinzu, das eine Zeile mit den von Ihnen aufgeführten Spalten anhängt, plus ID und Zeit des Anrufs.notify_team hinzu, das eine vom Agent geschriebene Nachricht in einem Slack-Kanal postet (Incoming Webhook).Die Steuerungsebene von EvaSay führt diese Funktionen mit dem verbundenen Konto aus; weder der Worker noch die Agent-Definition halten die Zugangsdaten der App. Beim Lesen eines Agents über die API erscheinen sie als kind: "app" (mit app, action, connection_id, app_config); senden Sie sie beim Ersetzen von tools unverändert zurück, um sie zu behalten. Apps werden nur im Dashboard verbunden.
Setzen Sie run_at_start: true bei einem der Tools eines Agents, und es wird zu Beginn jedes Anrufs aufgerufen, bevor der Agent grüßt oder antwortet. Parameter namens caller_number, called_number, direction, channel oder call_id werden dafür ausgefüllt. Die zurückgegebenen Felder füllen {{variables}} in first_message, system_prompt und idle_messages (Felder eine Ebene tiefer als {{customer.name}}), und die gesamte Antwort erhält der Agent als Hintergrund. Eine Begrüßung mit Variablen wartet bis zu 3 Sekunden auf die Antwort; was nicht gefunden wird, bleibt leer. Pro Agent kann ein Tool beim Start laufen.
Zugangsdaten werden in der Serverumgebung für Ihren Workspace und Ihr Ziel konfiguriert; bitten Sie support@evasay.com, eine credential_ref einzurichten. Legen Sie keine API-Schlüssel in Agent-Definitionen, Header, Prompts oder Tool-Parameter. Ihr Adapter kann CRM-Zugangsdaten in seiner eigenen Umgebung halten.
Sehen Sie sich ein Tool in der Vorschau an, bevor Sie Requests an das Geschäftssystem senden:
{
"arguments": { "customer_id": "customer-123" },
"dry_run": true,
"mock_result": { "name": "Alex", "order_status": "shipped" }
}
Eine Vorschau prüft die Parameter und zeigt den abgebildeten Request; sie führt kein Gespräch und kontaktiert das Geschäftssystem nicht. Setzen Sie dry_run=false für eine echte Ausführung. Ein echter Schreibtest erfordert zusätzlich confirmed=true und idempotency_key (8–128 Buchstaben, Ziffern, Punkte, Unterstriche, Doppelpunkte oder Bindestriche). Testantworten enthalten ok, status, duration_ms und ein begrenztes Ergebnis. Sie geben keine Zugangsdaten zurück. Lese- und Schreibtests erfordern Schreibrechte im Workspace.
Während eines Anrufs tragen Geschäfts-Requests einen stabilen Idempotency-Key. Ihr Geschäftsendpunkt muss ihn beachten. Identische Schreibvorgänge innerhalb eines Anrufs werden dedupliziert, auch Operationen mit unbekanntem Ausgang nach einem Timeout. Eine andere, beabsichtigte Operation braucht ein eigenes Geschäftsargument, etwa operation_id. EvaSay wiederholt Schreibvorgänge nicht automatisch. Ereignisse zur Tool-Ausführung enthalten Status und Dauer; die Funktion Gesprächstests bleibt eine Textsimulation, kein Test der Tool-Ausführung.
Konfigurieren Sie eine Streamable HTTP-MCP-Verbindung mit:
URL: https://evasay.com/api/v1/voice/mcp
Authorization: Bearer <your EvaSay API key>
In Claude Code zum Beispiel:
claude mcp add --transport http evasay https://evasay.com/api/v1/voice/mcp --header "Authorization: Bearer $EVASAY_API_KEY"
Die Verbindung sagt dem Tool, wie es einen Agent baut: den Katalog lesen, einen Entwurf anlegen, Wissen, Funktionen und Wortlisten hinzufügen, Tests schreiben und ausführen, den Entwurf korrigieren, bis sie bestehen, Ihnen die dashboard_url des Agents zum Ausprobieren geben und erst nach Ihrer Freigabe veröffentlichen und eine Nummer zuweisen. Tools, die Dokumentation lesen, können bei https://evasay.com/llms.txt beginnen; dort sind diese Seite, der OpenAPI-Vertrag und die MCP-Adresse verlinkt.
Nutzen Sie die sichere Token- oder Umgebungsvariablen-Einstellung des Clients. Der Endpunkt nutzt Authentifizierung per API-Schlüssel, keinen OAuth-Anmeldeablauf. Er stellt Agent-Erstellung/-Konfiguration, Bibliotheks-Tools, Wissen, Webhooks und Anrufprotokolle bereit. Veröffentlichen und echte Anrufe sind Schreibaktionen; ausgehende Anrufe verbrauchen Credits und Telefongebühren. Jeder Tool-Aufruf prüft die Workspace-Berechtigungen erneut. Aktivieren Sie die Bestätigungsfunktionen Ihres Clients für Schreibaktionen. Der Endpunkt nutzt zustandslose JSON-Antworten; einen Benachrichtigungsstream im Hintergrund bietet er nicht.
Eine Beispielanweisung für das Coding-Tool: „Erstelle einen EvaSay-Agent als Entwurf, registriere meinen CRM-Abfrage-Endpunkt, sieh ihn mit Testargumenten in der Vorschau an, binde ihn an den Agent und konfiguriere einen call.analyzed-Webhook.“ Prüfen und genehmigen Sie Veröffentlichung und echte Anrufe ausdrücklich.
POST /mcp/discover akzeptiert { "url": "https://crm.example.com/mcp", "credential_ref": "crm" } und liefert die Tools und Schemas des Servers. Registrieren Sie nur das ausgewählte Tool:
{
"name": "lookup_customer",
"description": "Find a CRM customer by confirmed ID.",
"kind": "mcp",
"url": "https://crm.example.com/mcp",
"mcp_tool": "get_customer",
"credential_ref": "crm",
"read_only": true,
"input_schema": {
"type": "object",
"properties": { "customer_id": { "type": "string" } },
"required": ["customer_id"]
}
}
Nur registrierte Tools stehen dem Agent zur Verfügung. Entfernte Verbindungen unterstützen Streamable HTTP mit JSON- oder SSE-Antworten auf Requests, öffentliche HTTPS-Ziele und vorkonfigurierte Zugangsdaten. Alte SSE-Endpunkte, OAuth-Aushandlung, vom Server ausgelöstes Sampling/Elicitation und binäre Anhänge werden nicht unterstützt. Das Finden gewährt nicht automatisch Zugriff auf alle Tools des Servers. Das Schema des entfernten Tools muss inline sein und die unterstützte Teilmenge von JSON Schema verwenden.
Erstellen Sie einen Webhook über POST /webhooks mit { "url": "https://crm.example.com/evasay-events", "events": ["call.analyzed"] }. Die Antwort enthält das Abonnement und ein erzeugtes Signatur-Secret, das nur beim Erstellen zurückgegeben wird. Prüfen Sie EvaSay-Signature, deduplizieren Sie über EvaSay-Delivery und aktualisieren Sie Ihr CRM. Ereignis-Webhooks sind asynchrone Benachrichtigungen; Tools während des Anrufs geben ihre Ergebnisse direkt an den Agent zurück.