https://a.storyblok.com/f/270183/1368x665/72cf89851e/26sep-tool_and_human_transfer_vonage_deepgram_agent-blog_r2.jpg

„Tools“ und „Human Transfer“ zu einem Vonage + Deepgram-Voice-Agenten hinzufügen

Zuletzt aktualisiert am September 22, 2026

Lesedauer: 9 Minuten

Einführung

Der Leitfaden zur Vonage Voice API und Deepgram bringt Sie überraschend weit. 

Am Ende dieser Anleitung können Sie eine Vonage-Nummer anrufen, mit einem KI-Agenten sprechen, ihn unterbrechen, während er spricht, und ein natürliches Voice-Gespräch führen, das auf der Voice Agent API von Deepgram ermöglicht wird. 

Aber der Agent kann immer noch nicht wirklich viel für dich tun (er hat keine Werkzeuge!). 

Bittet ihr den Agenten, eine Aktion auszuführen, und sofern die Informationen zu dieser Aktion nicht zufällig in der Eingabeaufforderung enthalten sind, kann er nirgendwo danach suchen. Gebt ihr eine Aufgabe, die von einem anderen System abhängt, und schon habt ihr ein weiteres Problem: Der Aufrufer wartet, bis dieses System antwortet. 

Voice macht solche Details sehr schnell deutlich. Ein langsamer API-Aufruf sieht nicht wie ein Lade-Symbol aus, sondern hört sich wie Funkstille an. 

Dieses audio-spezifische Problem für KI-Agenten wurde in „Don’t Loop the Latency: Where Agent Loops Belong in Voice AI“. Eine der Ideen in seinem Beitrag ist es, den Arbeitsaufwand während eines Live-Telefonats gering und vorhersehbar zu halten. 

Das Ziel dieses Beitrags ist es, die Dialog-Demo in einen Agenten umzuwandeln, der nützliche Aufgaben erledigen kann, vorhersehbare Fehler macht und – was am wichtigsten ist – genügend Informationen hinterlässt, um ihn später zu verbessern. In diesem Tutorial werden wir den bestehenden Vonage + Deepgram-Agenten so erweitern, dass er folgende Funktionen ausführen kann: 

  • dem Mitarbeiter ein Tool zur Überprüfung des Bestellstatus zur Verfügung stellen 

  • Eine feste Zeitbegrenzung für die Suche festlegen 

  • Fehler behandeln, ohne den Aufrufer warten zu lassen 

  • Weiterleitung von Anfragen, die der Agent nicht bearbeiten kann, an eine echte Telefonnummer 

  • die Ereignisse jedes Anrufs protokollieren 

TL;DR Die Schnellstartanleitung ist verfügbar auf GitHub.   

Voraussetzungen

Du benötigst: 

  • Eine Vonage-Application mit aktivierter Voice-Funktion 

  • Eine mit dieser Anwendung verknüpfte Vonage-Telefonnummer 

  • Eine zweite Telefonnummer, die Sie als Kontaktnummer für den Support durch einen Mitarbeiter nutzen können 

Gib dem Agenten ein Werkzeug

Wir halten den Anwendungsfall bewusst einfach: die Überprüfung des Bestellstatus. Der Aufrufer sagt: 

„Wo ist die Bestellung A1001?“ 

Deepgram erkennt, dass der Mitarbeiter externe Informationen benötigt, und fordert unsere Anwendung auf, folgenden Aufruf auszuführen: 

getOrderStatus("A1001") 

Unsere Anwendung führt die Suche durch und sendet das Ergebnis an Deepgram zurück. Das Modell wandelt dieses Ergebnis dann in eine natürliche gesprochene Antwort um. 

In diesem Tutorial wird das Bestell-Backend simuliert. Sie können es später durch Ihre eigene Datenbank oder API ersetzen; wir benötigen lediglich eine Abfrage, die erfolgreich sein, fehlschlagen oder zu lange dauern kann:

// src/tools/order-status.ts 
 
type OrderResult = 
  | { status: "in_transit"; estimatedDelivery: string } 
  | { status: "delivered"; deliveredAt: string } 
  | { status: "not_found" } 
  | { status: "error"; reason: string }; 
 
const KNOWN_ORDERS: Record<string, OrderResult> = { 
  A1001: { 
    status: "in_transit", 
    estimatedDelivery: "2026-07-29" 
  }, 
  A1002: { 
    status: "delivered", 
    deliveredAt: "2026-07-24T16:42:00Z" 
  } 
};

Außerdem gibt es einige spezielle Bestell-IDs für Testzwecke: 

  • Bei IDs, die mit „SLOW“ beginnen, dauert die Rückgabe zwei Sekunden. 

  • IDs, die mit „FAIL“ beginnen, simulieren einen vorübergehenden Netzwerkausfall. 

  • Alles andere führt zu „not_found“. 

Dadurch können wir die Verhaltensweisen nachbilden, die wir letztendlich von einer echten Datenbank oder einer externen API erwarten würden, ohne für dieses Tutorial ein vollständiges Backend entwickeln zu müssen. 

Das Tool bei Deepgram registrieren

The Voice API from Deepgram supports den Aufruf von clientseitigen Funktionen. Wir beschreiben die Funktion in der „Einstellungen“-Nachricht des Agenten:

// src/agent/agent-config.ts 
const GET_ORDER_STATUS_FUNCTION = { 
  name: "getOrderStatus", 
  description: 
    "Look up the current shipping status of a single order by its order number.", 
  parameters: { 
    type: "object", 
    properties: { 
      orderId: { 
        type: "string", 
        description: 'The caller\'s order number, for example "A1001".' 
      } 
    }, 
    required: ["orderId"] 
  } 
};

Wir geben Deepgram keinen HTTP-Endpunkt für die Funktion an. Stattdessen sendet Deepgram eine „FunctionCallRequest“-Anfrage an unseren WebSocket. Das bedeutet, dass unsere Anwendung weiterhin die Kontrolle über die tatsächliche Ausführung des Tools behält. 

Das ist nützlich, weil wir so entscheiden können: 

  • ob das Werkzeug zulässig ist 

  • wie lange es laufen kann 

  • ob ein Fehlversuch wiederholt werden soll 

  • Was der Anrufer hört, wenn es nicht funktioniert 

Auch die Eingabeaufforderung des Agenten bleibt begrenzt:

// src/agent/agent-config.ts (SYSTEM_PROMPT constant) 
You are an order-status voice agent for a live phone call. 
 
You may ONLY help the caller check the status of an order. 
 
Rules: 
- Ask for the caller's order number if they have not provided it. 
- Call getOrderStatus exactly once with the order number. 
- You can look up only one order per call. 
- If the result is clear, read it back in one or two natural spoken sentences. 
- If the lookup fails or times out, use the fallback response. 
- If the caller asks about billing, returns, disputes, or anything else, 
  use the handoff response immediately. 
- Do not answer general questions. 
- Do not make up information.

Die Eingabeaufforderung gibt dem Modell vor, was zu tun ist, aber wir verlassen uns nicht allein auf die Eingabeaufforderung. Bevor eine Auftragsabfrage durchgeführt wird, überprüft die Anwendung, ob die Anfrage im Gültigkeitsbereich liegt und ob das Tool bei diesem Aufruf noch nicht verwendet wurde. Wie dies funktioniert, erfahren Sie im Abschnitt „Behandlung des Funktionsaufrufs“. 

Legen Sie eine Frist für die Recherche fest

An dieser Stelle unterscheidet sich die Entwicklung für einen Telefonanruf von der Entwicklung eines normalen Chatbots. Stellen Sie sich vor, der Bestelldienst benötigt sechs Sekunden für die Antwort. Aus Sicht des Servers ist das lediglich eine langsame Anfrage. 

Aus Sicht des Anrufers stellte er eine Frage und hörte dann sechs Sekunden lang nichts. 

In diesem Beispiel dauert die Abfrage also 1500 Millisekunden:

// src/agent/tool-policy.ts 
export const TOOL_TIMEOUT_MS = 1500; 

Der Wrapper führt den Backend-Aufruf unter Einhaltung dieser Frist aus:

// src/tools/order-status.ts  
export async function lookupOrderStatus( 
  orderId: string, 
  timeoutMs: number = TOOL_TIMEOUT_MS 
): Promise<OrderLookupOutcome> { 
  const startedAt = Date.now(); 
 
  let timer: ReturnType<typeof setTimeout> | undefined; 
 
  const timeout = new Promise<"__timeout__">((resolve) => { 
    timer = setTimeout(() => resolve("__timeout__"), timeoutMs); 
  }); 
 
  try { 
    const raced = await Promise.race([ 
      getOrderStatus(orderId), 
      timeout 
    ]); 
 
    if (raced === "__timeout__") { 
      return { 
        kind: "timeout", 
        durationMs: Date.now() - startedAt 
      }; 
    } 
 
    return { 
      kind: "result", 
      result: raced, 
      durationMs: Date.now() - startedAt 
    }; 
  } catch (err) { 
    return { 
      kind: "transport_error", 
      error: new TransportError( 
        err instanceof Error ? err.message : "unknown tool failure" 
      ), 
      durationMs: Date.now() - startedAt 
    }; 
  } finally { 
    if (timer) clearTimeout(timer); 
  } 
}

Das Wichtigste ist, dass es drei mögliche Ergebnisse gibt: 

Ergebnis 

Was das bedeutet 

Was wir tun 

Ergebnis 

Das Backend hat geantwortet 

Das Ergebnis zurückgeben 

Zeitüberschreitung 

Es hat nicht innerhalb von 1500 ms geantwortet. 

Verwende die Ausweichlösung 

transport_error 

Die Verbindung ist fehlgeschlagen 

Es noch einmal versuchen 

Eine „not_found“-Antwort gilt dennoch als erfolgreicher Abruf. Das Backend hat geantwortet; es hat lediglich die Bestellung nicht gefunden. 

Das ist etwas anderes als eine Auszeit. 

Beschränken Sie, was während des Anrufs passieren kann

In diesem Beispiel sind die Regeln bewusst minimal gehalten:

// src/agent/tool-policy.ts 
export const MAX_TOOL_CALLS = 1; 
export const MAX_RETRIES = 1; 
export const ALLOWED_TOOLS = ["getOrderStatus"] as const; 

Für jeden Anruf wird eine eigene Policy-Instanz erstellt:

// src/agent/tool-policy.ts  
export function createToolPolicy() { 
  let callsMade = 0; 
  let retriesUsed = 0; 
 
  return { 
    authorizeCall(toolName: string) { 
      if (toolName !== "getOrderStatus") { 
        return { allowed: false }; 
      } 
 
      if (callsMade >= MAX_TOOL_CALLS) { 
        return { allowed: false }; 
      } 
 
      return { allowed: true }; 
    }, 
 
    recordCall() { 
      callsMade += 1; 
    }, 
 
    authorizeRetry(outcome: OrderLookupOutcome) { 
      if (outcome.kind !== "transport_error") { 
        return { allowed: false }; 
      } 
 
      if (retriesUsed >= MAX_RETRIES) { 
        return { allowed: false }; 
      } 
 
      return { allowed: true }; 
    }, 
 
    recordRetry() { 
      retriesUsed += 1; 
    } 
  }; 
}

Bei einer Zeitüberschreitung erfolgt kein erneuter Versuch. 

Wir haben bereits 1,5 Sekunden gewartet. Wenn wir dieselbe langsame Anfrage erneut starten, könnte das einfach zu weiteren 1,5 Sekunden Stille führen. 

Bei einem Übertragungsfehler wird ein Wiederholungsversuch unternommen, da sich eine unterbrochene Verbindung oder ein vorübergehendes Problem auf der Upstream-Seite möglicherweise sofort beheben lässt. 

Den Funktionsaufruf verarbeiten

Wenn Deepgram eine „FunctionCallRequest“-Anfrage sendet, wendet der WebSocket-Handler diese Regeln an, bevor das Tool ausgeführt wird. 

Der Hauptablauf ist wie folgt:

// src/voice/websocket-handler.ts  
async function handleFunctionCall(fn: DeepgramFunctionCall) { 
  // Is this request supported? 
  const handoffReason = 
    classifyHandoffReason(lastCallerUtterance); 
 
  if (handoffReason) { 
    requestHandoff(handoffReason); 
 
    respondToFunction( 
      fn, 
      JSON.stringify({ status: "handoff" }) 
    ); 
 
    return; 
  } 
 
  // Has the tool already been called? 
  const auth = policy.authorizeCall(fn.name); 
 
  if (!auth.allowed) { 
    fallbackUsed = true; 
    inject(FALLBACK_RESPONSE); 
 
    respondToFunction( 
      fn, 
      JSON.stringify({ status: "blocked" }) 
    ); 
 
    return; 
  } 
 
  policy.recordCall(); 
 
  // Run the lookup 
  let outcome = await lookupOrderStatus(orderId); 
 
  // Retry one transport failure 
  if ( 
    outcome.kind === "transport_error" && 
    policy.authorizeRetry(outcome).allowed 
  ) { 
    policy.recordRetry(); 
    outcome = await lookupOrderStatus(orderId); 
  } 
 
  // Return a successful result 
  if (outcome.kind === "result") { 
    respondToFunction( 
      fn, 
      JSON.stringify(outcome.result) 
    ); 
    return; 
  } 
 
  // Otherwise use the fallback 
  fallbackUsed = true; 
  inject(FALLBACK_RESPONSE); 
}

Der eigentliche Handler protokolliert ebenfalls den Aufruf des Tools und den Zeitpunkt, doch dieser Teil bestimmt, was der Aufrufer wahrnimmt. 

Verwenden Sie einen festen Fallback

Sollte die Suche fehlschlagen, soll das Modell keinen eigenen Wiederherstellungsplan entwickeln. 

The application adds a fixed answer:

// src/agent/fallback-responses.ts 

export const FALLBACK_RESPONSE = 
  "I'm having trouble retrieving that order right now. " + 
  "Please try again later, or contact our support team and they can help.";

Mit „InjectAgentMessage“ von Deepgram können wir diese Antwort direkt in die Unterhaltung einfügen:

// src/voice/websocket-handler.ts 
sendJson(dg, { 
  type: "InjectAgentMessage", 
  message: FALLBACK_RESPONSE, 
  behavior: "interrupt" 
}); 

Das Interrupt-Verhalten spielt hier eine Rolle. 

Wenn Sie das Standardverhalten verwenden, kann es vorkommen, dass eine eingefügte Nachricht abgelehnt wird, während der Anrufer gerade spricht. Das möchten Sie sicher nicht erst feststellen, wenn die eingefügte Nachricht Ihren Ausfallpfad darstellt. 

Beachten Sie außerdem den Feldnamen: Er lautet „message“ und nicht „content“. 

Beides sind kleine Details, die andernfalls dazu führen können, dass ein Gespräch plötzlich verstummt, ohne dass es dafür einen erkennbaren Grund gibt. 

Nicht unterstützte Anfragen an einen Mitarbeiter weiterleiten

Ein Mitarbeiter im Auftragsstatus-Support sollte nicht versuchen, alle Fragen zu beantworten. 

Wenn jemand sagt: 

„Ich möchte eine Abbuchung beanstanden.“ 

Wir stufen dies als Abrechnungsanfrage ein:

// src/agent/tool-policy.ts 

export type HandoffReason = 
  | "billing" 
  | "returns" 
  | "cancellation" 
  | "account" 
  | "unsupported"; 

In dieser Demo ist die Klassifizierung bewusst eingeschränkt und deterministisch:

// src/agent/tool-policy.ts  

const HANDOFF_KEYWORDS = [ 
  ["cancellation", ["cancel", "cancellation"]], 
  ["returns", ["return", "returns", "refund", "exchange"]], 
  [ 
    "billing", 
    ["billing", "invoice", "charge", "payment", "dispute"] 
  ], 
  ["account", ["account", "password", "login", "access"]] 
];

Hier gibt es keinen zweiten Modellaufruf. 

Wenn der Anrufer etwas verlangt, das nicht in den Aufgabenbereich des Mitarbeiters fällt, wissen wir, dass wir jedes Mal dasselbe Ergebnis anstreben: den Anruf an eine andere Person weiterleiten.

// src/voice/websocket-handler.ts 

function requestHandoff(reason: HandoffReason): void { 
  if (handoffRequested) return; 
 
  handoffRequested = true; 
  handoffReason = reason; 
 
  void transferToHuman(callUuid, reason).catch((err) => { 
    console.error[transfer] failed: ${String(err)}); 
  }); 
} 

Die Funktion „transferToHuman()“ aktualisiert den aktiven Vonage-Anruf mit einer neuen NCCO. 

Der NCCO informiert den Anrufer zunächst darüber, was gerade passiert, und leitet den Anruf dann an die Support-Nummer weiter:

// src/voice/transfer-to-human.ts  

const ncco = [ 
  { 
    action: "talk", 
    text: "That's something our support team handles directly. Let me connect you now.", 
    language: "en-US" 
  }, 
  { 
    action: "connect", 
    from: process.env.VONAGE_NUMBER, 
    endpoint: [ 
      { 
        type: "phone", 
        number: process.env.SUPPORT_PHONE_NUMBER 
      } 
    ] 
  } 
];

Anschließend leiten wir den aktiven Anruf weiter:

// src/voice/transfer-to-human.ts 
await fetch( 
  https://api.nexmo.com/v1/calls/${callUuid}, 
  { 
    method: "PUT", 
    headers: { 
      Authorization: Bearer ${jwt}, 
      "Content-Type": "application/json" 
    }, 
    body: JSON.stringify({ 
      action: "transfer", 
      destination: { 
        type: "ncco", 
        ncco 
      } 
    }) 
  } 
);

Für lokale Tests kann „SUPPORT_PHONE_NUMBER“ einfach ein anderes Telefon sein, das Sie gerade zur Hand haben. 

Rufen Sie Ihre Vonage-Nummer von einem Telefon aus an, beantragen Sie die Anfechtung einer Gebühr, und das andere Telefon sollte klingeln. 

Das ist eine viel bessere Ausweichlösung, als dass die KI so tut, als könne sie ein Abrechnungsproblem lösen, auf das sie nie Zugriff hatte.

Übertragung konfigurieren

Damit die eigentliche Übergabe funktioniert, fügen Sie diese Werte Ihrer Umgebung hinzu:

# .env.example 

VONAGE_APP_ID=your_application_id 
VONAGE_PRIVATE_KEY_PATH=./vonage_private.key 
VONAGE_NUMBER=15551234567 
SUPPORT_PHONE_NUMBER=15557654321

 Außerdem benötigen Sie die bestehende Konfiguration:

# .env.example 

DEEPGRAM_API_KEY=your_deepgram_key 
BASE_URL=https://your-ngrok-url.ngrok-free.app 
DB_PATH=./calls.db 
AGENT_VERSION=order-status-v1 

Verwenden Sie für die Vonage- und Support-Nummern Numbers im E.164-Format. 

Das, was während des Gesprächs passiert ist, speichern

The application also writes a small dataset to SQLite when the call ends. 

Das ist nicht die Bestelldatenbank. Es handelt sich um eine Aufzeichnung der Voice-Interaktion selbst.

-- src/storage/db.ts 

CREATE TABLE IF NOT EXISTS call_records ( 
  call_id            TEXT PRIMARY KEY, 
  agent_version      TEXT NOT NULL, 
  started_at         TEXT NOT NULL, 
  ended_at           TEXT NOT NULL, 
  transcript         TEXT NOT NULL, 
  tool_calls         TEXT NOT NULL, 
  latency            TEXT NOT NULL, 
  fallback_used      INTEGER NOT NULL, 
  handoff_requested  INTEGER NOT NULL, 
  handoff_reason     TEXT, 
  outcome            TEXT NOT NULL 
);

Ein Datensatz kann uns Folgendes verraten: 

  • Was der Anrufer und der Mitarbeiter gesagt haben 

  • Welches Tool wurde aufgerufen? 

  • wie lange es gedauert hat 

  • ob der Fallback verwendet wurde 

  • ob der Anrufer weitergeleitet wurde 

  • warum der Wechsel stattfand 

  • wie das Gespräch endete 

Ein Anruf zur Rechnungsstellung könnte beispielsweise in etwa so ablaufen:

{ 
  "agentVersion": "order-status-v1", 
  "fallbackUsed": false, 
  "handoffRequested": true, 
  "handoffReason": "billing", 
  "outcome": "handoff" 
} 

Das ist nützlich, auch wenn man nie ein kompliziertes Auswertungssystem darauf aufbaut. 

Wenn Anrufer aus demselben Grund immer wieder weitergeleitet werden, können Sie das erkennen. Wenn die Timeouts zunehmen, können Sie das ebenfalls erkennen. Und wenn Sie später die Ansage, das Modell oder die Tools ändern, können Sie anhand des Felds „agent_version“ auf einfache Weise feststellen, welche Version welche Anrufe bearbeitet hat. 

So führen Sie den Agenten aus

Starten Sie zunächst ngrok:

ngrok http 3000 

Tragen Sie diese HTTPS-URL in „BASE_URL“ sowie in die Webhooks „Answer“ und „Event“ Ihrer Vonage-Application ein. 

Starten Sie anschließend die Anwendung:

npm run dev

Sie können den Antwort-Webhook einer Plausibilitätsprüfung unterziehen, bevor Sie einen Anruf tätigen:

curl "https://YOUR-NGROK-URL/answer?uuid=test123&from=15551234567" 

Der zurückgegebene NCCO sollte einen WebSocket-Endpunkt enthalten, der in etwa wie folgt aussieht: 

wss://YOUR-NGROK-URL/socket?callUuid=test123 

Probieren Sie „Four Calls“ aus

Versuchen Sie doch einmal, die wichtigsten Funktionen als separate Telefonanrufe zu testen. 

Anruf 

Was soll man sagen? 

Was sollte passieren? 

1 

„Wo ist die Bestellung A1001?“ 

Der Mitarbeiter liest den Lieferstatus vor 

2 

„Wo ist die Bestellung SLOW999?“ 

Die Abfrage läuft ab und die festgelegte Ausweichoption wird abgespielt 

3 

„Wo ist die Bestellung XYZ123?“ 

Der Mitarbeiter teilt Ihnen mit, dass die Bestellung nicht gefunden werden konnte 

4 

„Ich möchte eine Abbuchung beanstanden.“ 

Der Anruf wird an Ihre Support-Telefonnummer weitergeleitet 

Führen Sie für jeden Aufruf eine neue Abfrage durch. In diesem Beispiel ist pro Aufruf eine Bestellabfrage zulässig. 

Überprüfen Sie anschließend die Datensätze:

sqlite3 calls.db \ 
  "SELECT 
     call_id, 
     agent_version, 
     outcome, 
     fallback_used, 
     handoff_requested, 
     handoff_reason 
   FROM call_records 
   ORDER BY started_at DESC 
   LIMIT 4;" 

Sie sollten die verschiedenen Pfade erkennen können, die in den Daten dargestellt sind: 

abgeschlossen 
Fallback 
abgeschlossen 
Übergabe 

Beim letzten Anruf sollte „handoff_reason“ den Wert „billing“ haben. 

Schlussfolgerung

Das ursprüngliche Vonage + Deepgram-Tutorial zeigt, wie ein dialogorientierter KI-Agent in ein echtes Telefongespräch eingebunden wird. Hier haben wir diesem Agenten eine nützliche Aufgabe zugewiesen: eine Bestellung nachschlagen, das Warten beenden, wenn das Backend zu langsam ist, bei Fehlern sauber ausweichen und nicht unterstützte Anfragen an einen Menschen weiterleiten. 

Das Bestell-Backend ist simuliert, aber das Muster bleibt dasselbe, wenn Sie `getOrderStatus()` durch Ihre eigene Datenbank oder API ersetzen. 

So lässt sich Vince’ Idee „Keine Latenz in Schleifen einbinden“ in der Praxis umsetzen: Während der Aufrufer wartet, sollte man den Arbeitsaufwand gering halten, Fristen für externe Aufrufe festlegen und einen sinnvollen Ausweg bereitstellen. 

Nach dem Anruf entfallen diese zeitlichen Einschränkungen. Genau hier kommen die von uns gespeicherten Datensätze, Mitschriften, Tool-Aufrufe, Ergebnisse, Gründe für die Übergabe und Agentenversionen zum Einsatz. 

Wenn beispielsweise „Rücksendungen“ wiederholt als Grund für die Übergabe auftauchen, können wir diese Anrufe nutzen, um zu entscheiden, was als Nächstes entwickelt werden soll, einer in Frage kommenden Version eine Rücksendefunktion hinzufügen und diese anhand der gespeicherten Anrufe testen, bevor wir sie den Anrufern zur Verfügung stellen. 

Das ist der Anfang eines Workflows im Bereich Loop-Engineering. Aber das ist ein Thema für den nächsten Beitrag!

Haben Sie eine Frage oder möchten Sie uns mitteilen, was Sie gerade bauen?

Bleiben Sie auf dem Laufenden und halten Sie sich über die neuesten Nachrichten, Tipps und Veranstaltungen für Entwickler auf dem Laufenden.

Teilen Sie:

https://a.storyblok.com/f/270183/384x384/e4e7d1452e/benjamin-aronov.png
Benjamin AronovAdvokat für Entwickler

Benjamin Aronov ist ein Entwickler-Befürworter bei Vonage. Er ist ein bewährter Community Builder mit einem Hintergrund in Ruby on Rails. Benjamin genießt die Strände von Tel Aviv, das er sein Zuhause nennt. Von Tel Aviv aus kann er einige der besten Startup-Gründer der Welt treffen und von ihnen lernen. Außerhalb der Tech-Branche reist Benjamin gerne um die Welt auf der Suche nach dem perfekten Pain au Chocolat.