Vue d'ensemble du SDK

Le SDK Vonage Cloud Runtime constitue l'interface principale avec tous les fournisseurs de plateformes. Il est disponible pour Node.js et Python.

Temps d'exécution Paquet Version minimale Dernière version Notes
Node.js @vonage/vcr-sdk 2.0.0 2.1.5 SDK >=2.1.0 nécessite Node.js 22 (Active LTS)
Python vonage_cloud_runtime 2.0.0 2.1.5

Les vcr Singleton

Le SDK exporte un vcr singleton qui est le point d'entrée pour toutes les opérations.

Node.js :

import { vcr } from '@vonage/vcr-sdk';

Python :

from vonage_cloud_runtime.vcr import VCR
vcr = VCR()

Les vcr fournit les méthodes suivantes :

Méthode Description
vcr.createSession(ttl?) Créer une nouvelle session avec un TTL optionnel en secondes (par défaut : 7 jours)
vcr.createSessionWithId(id) Créer une session avec un identifiant spécifique
vcr.getSessionById(id) Récupérer une session existante par ID
vcr.getSessionFromRequest(req) Extraire la session d'une requête HTTP entrante
vcr.getGlobalSession() Obtenir la session globale (partagée entre toutes les demandes)
vcr.getInstanceState() Obtenir l'état de l'instance (partagé entre les sessions au sein de l'instance)
vcr.getAccountState() Obtenir un état au niveau du compte (partagé par toutes les applications du compte)
vcr.getAppUrl() Obtenir l'URL publique de l'application en cours d'exécution
vcr.createVonageToken(params) Créer un JWT signé pour l'authentification de l'API Vonage
vcr.verifyAuth(token) Verify un jeton d'authentification
vcr.unsubscribe(id, provider?) Se désabonner d'un abonnement à un fournisseur

Sessions

Les sessions sont nécessaires pour initialiser tout fournisseur. Chaque constructeur de fournisseur prend une session comme premier argument.

Node.js :

import { vcr } from '@vonage/vcr-sdk';

// New session with default 7-day TTL
const session = vcr.createSession();

// New session with a 1-hour TTL
const shortSession = vcr.createSession(3600);

// Session with a specific ID (useful for correlating with a user or call)
const userSession = vcr.createSessionWithId('user-123');

// Extract session from an incoming request
const reqSession = vcr.getSessionFromRequest(req);

// Global session — shared singleton across the entire instance
const globalSession = vcr.getGlobalSession();

Python :

from vonage_cloud_runtime.vcr import VCR
vcr = VCR()

session = vcr.createSession()           # default 7-day TTL
session = vcr.createSession(3600)       # 1-hour TTL
session = vcr.createSessionWithId('user-123')
session = vcr.getSessionFromRequest(req)
session = vcr.getGlobalSession()

Propriétés et méthodes de la session :

Description
session.id L'identifiant unique de la session
session.getToken() Obtenir le jeton d'authentification de la session
session.createUUID() Générer un nouvel UUID
session.log(level, message, context?) Enregistrer un message avec un contexte structuré

Définition du champ d'application de la session - Orientations essentielles

Avertissement : vcr.createSession() génère un aléatoire, éphémère à chaque fois qu'il est appelé. Les données stockées sous cette session (via new State(session)) n'est accessible que si vous disposez de l'identifiant de session exact. Si vous appelez vcr.createSession() au niveau global/module et l'utiliser avec State, chaque réplique créera une session différenteLes répliques et les données seront cloisonnées et inaccessibles à d'autres répliques ou requêtes. Cela met fin à l'architecture sans état.

Règles :

  • Jamais appel vcr.createSession() à l'échelle globale de l'application pour initialiser State ou d'autres fournisseurs qui ont besoin d'un accès partagé aux données.
  • Pour l'état partagé entre les répliques, utiliser vcr.getInstanceState() (ou vcr.getAccountState() pour les données inter-applications).
  • Pour l'état par demande ou par conversation, utiliser vcr.createSessionWithId(id) avec un déterministe ID du contexte de la demande - tel que conversation_uuid d'un rappel vocal, un numéro de téléphone de l'expéditeur d'un rappel SMS, ou un identifiant d'utilisateur. Cela permet de s'assurer que la même session est récupérable à travers les répliques et les requêtes.
  • vcr.getGlobalSession() est destiné à enregistrer des abonnements à l'échelle de l'instance (par ex, voice.onCall(), messages.onMessage()). Il doit pas être utilisée comme session polyvalente pour l'État.
// WRONG — random session at global scope, state is unreachable by other replicas/requests
const session = vcr.createSession();
const state = new State(session); // Data siloed to this random session

// CORRECT — shared state across all replicas
const state = vcr.getInstanceState();

// CORRECT — per-conversation state using a deterministic ID from a callback
app.post('/onCall', async (req, res) => {
  const session = vcr.createSessionWithId(req.body.conversation_uuid);
  const state = new State(session); // Same conversation_uuid = same state, any replica
  await state.set('step', 'greeting');
});

Voir Architecture sans état pour des conseils détaillés.

Initialisation du fournisseur

Tous les fournisseurs suivent le même schéma : ils transmettent une session au constructeur.

Node.js :

import { vcr, State, Queue, Scheduler, Messages, Voice, Assets } from '@vonage/vcr-sdk';

const session = vcr.createSession();

// For shared state across replicas, use getInstanceState() — not new State(session)
const state     = vcr.getInstanceState();
const queue     = new Queue(session);
const scheduler = new Scheduler(session);
const messages  = new Messages(session);
const voice     = new Voice(session);
const assets    = new Assets(session);

Python :

from vonage_cloud_runtime.vcr import VCR
from vonage_cloud_runtime.providers.state.state import State
from vonage_cloud_runtime.providers.queue.queue import Queue
from vonage_cloud_runtime.providers.scheduler.scheduler import Scheduler
from vonage_cloud_runtime.providers.messages.messages import Messages
from vonage_cloud_runtime.providers.voice.voice import Voice
from vonage_cloud_runtime.providers.assets.assets import Assets

vcr = VCR()
session = vcr.createSession()

# For shared state across replicas, use getInstanceState() — not State(session)
state     = vcr.getInstanceState()
queue     = Queue(session)
scheduler = Scheduler(session)
messages  = Messages(session)
voice     = Voice(session)
assets    = Assets(session)

Portée de l'État

Le RCV offre trois niveaux d'état :

Champ d'application Comment accéder Visibilité
État de la session new State(session) Isolé à la session spécifique
État de l'instance vcr.getInstanceState() Partagé entre toutes les sessions d'une même instance
État du compte vcr.getAccountState() Partagé entre toutes les Applications du compte Vonage
// Per-user state
const session = vcr.createSessionWithId(userId);
const userState = new State(session);

// Shared across all replicas of this instance
const instanceState = vcr.getInstanceState();

// Shared across all applications in the account
const accountState = vcr.getAccountState();

Voir Architecture sans état pour savoir quand utiliser chaque champ d'application.

Authentification

Verify Incoming Requests (vérification des demandes entrantes)

Utilisation vcr.verifyAuth(token) pour valider les jetons sur les demandes entrantes :

app.use((req, res, next) => {
  const token = req.headers.authorization?.replace('Bearer ', '');
  try {
    const decoded = vcr.verifyAuth(token);
    req.user = decoded;
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
});

Création de jetons Vonage

Utilisation vcr.createVonageToken(params) pour générer des JWT signés pour l'authentification de l'API Vonage :

const token = vcr.createVonageToken({
  exp: Math.floor(Date.now() / 1000) + 3600, // 1-hour expiry
  aclPaths: { '/*/users/**': {} },            // optional ACL paths
  subject: 'user-123',                        // optional subject
});
Paramètres Type Exigée Description
exp Numbers Oui Expiration du jeton sous forme d'horodatage Unix (secondes)
aclPaths Enregistrement<chaîne, any> Non Restrictions des chemins d'accès ACL
subject chaîne de caractères Non Sujet du jeton (par exemple, identifiant de l'utilisateur)

Méthodes d'utilité

vcr.getAppUrl()

Renvoie l'URL publique de l'instance VCR en cours d'exécution. Cela équivaut à lire l'adresse VCR_INSTANCE_PUBLIC_URL variable d'environnement.

const appUrl = vcr.getAppUrl();
// e.g. "https://my-app-dev.use1.runtime.vonage.cloud"

vcr.unsubscribe(id, provider?)

Arrêter de recevoir des rappels d'un abonnement à un fournisseur :

const subId = await voice.onCall('onCall');

// Later, when you want to stop receiving calls:
await vcr.unsubscribe(subId, 'voice');

Structure d'une application typique

Node.js (Express) :

import express from 'express';
import { vcr, Voice, Messages, State } from '@vonage/vcr-sdk';

const app = express();
app.use(express.json());

// Use getGlobalSession() for registering instance-wide subscriptions.
// Do NOT use vcr.createSession() here — it creates a random session that
// cannot be shared across replicas or requests.
const globalSession = vcr.getGlobalSession();
const voice = new Voice(globalSession);
const messages = new Messages(globalSession);

await voice.onCall('onCall');
await messages.onMessage('onMessage',
  { type: 'sms', number: process.env.VONAGE_NUMBER },
  { type: 'sms', number: undefined }
);

app.post('/onCall', async (req, res) => {
  // Scope session to the conversation using its unique ID from the callback
  const session = vcr.createSessionWithId(req.body.conversation_uuid);
  const state = new State(session);
  await state.set('status', 'answered');
  res.json([{ action: 'talk', text: 'Hello from VCR!' }]);
});

app.post('/onMessage', async (req, res) => {
  // Scope session to the sender — deterministic, same across replicas
  const session = vcr.createSessionWithId(req.body.from);
  const state = new State(session);
  await state.set('lastMessage', req.body.text);
  res.sendStatus(200);
});

app.get('/_/health', (req, res) => res.sendStatus(200));

// Must bind to 0.0.0.0 — VCR routes traffic via an internal proxy
const port = process.env.VCR_PORT || 8080;
app.listen(port, '0.0.0.0');

Python (FastAPI) :

import os
from fastapi import FastAPI, Request
from vonage_cloud_runtime.vcr import VCR
from vonage_cloud_runtime.providers.voice.voice import Voice
from vonage_cloud_runtime.providers.messages.messages import Messages
from vonage_cloud_runtime.providers.state.state import State

app = FastAPI()
vcr = VCR()

# Use getGlobalSession() for registering instance-wide subscriptions.
# Do NOT use vcr.createSession() here — it creates a random session that
# cannot be shared across replicas or requests.
global_session = vcr.getGlobalSession()
voice = Voice(global_session)
messages = Messages(global_session)

@app.on_event("startup")
async def startup():
    await voice.onCall("onCall")
    await messages.onMessage("onMessage",
        {"type": "sms", "number": os.environ.get("VONAGE_NUMBER")},
        {"type": "sms", "number": None}
    )

@app.post("/onCall")
async def on_call(request: Request):
    body = await request.json()
    # Scope session to the conversation using its unique ID from the callback
    session = vcr.createSessionWithId(body.get("conversation_uuid"))
    state = State(session)
    await state.set("status", "answered")
    return [{"action": "talk", "text": "Hello from VCR!"}]

@app.post("/onMessage")
async def on_message(request: Request):
    body = await request.json()
    # Scope session to the sender — deterministic, same across replicas
    session = vcr.createSessionWithId(body.get("from"))
    state = State(session)
    await state.set("lastMessage", body.get("text"))
    return {"status": "ok"}

@app.get("/_/health")
async def health():
    return {"status": "ok"}

if __name__ == "__main__":
    import uvicorn
    port = int(os.environ.get("VCR_PORT", 8080))
    uvicorn.run(app, host="0.0.0.0", port=port)

Important : Liez toujours votre serveur à 0.0.0.0, pas localhost ou 127.0.0.1. VCR achemine le trafic entrant via un proxy interne et l'application ne sera pas joignable si elle n'écoute que sur l'interface de bouclage.