Visão geral do SDK
O Vonage Cloud Runtime SDK é a principal interface para todos os provedores de plataforma. Ele está disponível para Node.js e Python.
| Tempo de execução | Embalagem | Versão mínima | Versão mais recente | Notas |
|---|---|---|---|---|
| Node.js | @vonage/vcr-sdk | 2.0.0 | 2.1.5 | O SDK >=2.1.0 requer o Node.js 22 (LTS ativo) |
| Python | vonage_cloud_runtime | 2.0.0 | 2.1.5 |
O vcr Singleton
O SDK exporta um vcr singleton que serve como ponto de entrada para todas as operações.
Node.js:
import { vcr } from '@vonage/vcr-sdk';
Python:
from vonage_cloud_runtime.vcr import VCR
vcr = VCR()
O vcr O objeto oferece os seguintes métodos:
| Método | Descrição |
|---|---|
vcr.createSession(ttl?) | Criar uma nova sessão com TTL opcional em segundos (padrão: 7 dias) |
vcr.createSessionWithId(id) | Criar uma sessão com um ID específico |
vcr.getSessionById(id) | Recuperar uma sessão existente pelo ID |
vcr.getSessionFromRequest(req) | Extrair a sessão de uma solicitação HTTP recebida |
vcr.getGlobalSession() | Obter a sessão global (compartilhada entre todas as solicitações) |
vcr.getInstanceState() | Obter o estado no nível da instância (compartilhado entre as sessões dentro da instância) |
vcr.getAccountState() | Obter o estado da conta (compartilhado entre todos os aplicativos da conta) |
vcr.getAppUrl() | Obter a URL pública do aplicativo em execução |
vcr.createVonageToken(params) | Criar um JWT assinado para autenticação na API da Vonage |
vcr.verifyAuth(token) | Verificar um token de autenticação |
vcr.unsubscribe(id, provider?) | Cancelar a assinatura de um provedor |
Sessões
É necessário haver sessões para inicializar qualquer provedor. O construtor de cada provedor recebe uma sessão como primeiro argumento.
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()
Propriedades e métodos da sessão:
| Descrição | |
|---|---|
session.id | O identificador exclusivo da sessão |
session.getToken() | Obter o token de autenticação da sessão |
session.createUUID() | Gerar um novo UUID |
session.log(level, message, context?) | Registrar uma mensagem com contexto estruturado |
Definição do escopo da sessão — Orientações essenciais
Aviso: vcr.createSession() gera um aleatório, efêmero ID da sessão sempre que for chamado. Os dados armazenados nessa sessão (por meio de new State(session)) só pode ser acessado se você tiver exatamente esse ID de sessão. Se você chamar vcr.createSession() no escopo global/módulo e usá-lo com o State, cada réplica criará uma sessão diferente, e os dados ficarão isolados e inacessíveis para outras réplicas ou solicitações. Isso compromete a arquitetura sem estado.
Regras:
- Nunca chamada
vcr.createSession()no escopo global do aplicativo para inicializar o State ou outros provedores que necessitem de acesso a dados compartilhados. - Para estado compartilhado entre réplicas, use
vcr.getInstanceState()(ouvcr.getAccountState()(para dados entre aplicativos). - Para estado por solicitação ou por conversa, use
vcr.createSessionWithId(id)com um determinístico ID do contexto da solicitação — como, por exemplo,conversation_uuida partir de um retorno de chamada de voz, do número de telefone do remetente em um retorno de chamada por SMS ou de um ID de usuário. Isso garante que a mesma sessão possa ser recuperada em todas as réplicas e solicitações. vcr.getGlobalSession()destina-se ao registro de assinaturas válidas para toda a instância (por exemplo,voice.onCall(),messages.onMessage()). Deveria não ser usada como uma sessão de uso geral para o State.
// 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');
});
Veja Arquitetura sem estado para obter orientações detalhadas.
Inicialização do provedor
Todos os provedores seguem o mesmo padrão: passam uma sessão para o construtor.
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)
Análise do âmbito estadual
O VCR oferece três níveis de estado:
| Âmbito | Como acessar | Visibilidade |
|---|---|---|
| Estado da sessão | new State(session) | Restrito à sessão específica |
| Estado da instância | vcr.getInstanceState() | Compartilhado entre todas as sessões dentro da mesma instância |
| Status da conta | vcr.getAccountState() | Compartilhado entre todas as aplicações da conta da 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();
Veja Arquitetura sem estado para obter orientações sobre quando usar cada escopo.
Autenticação
Verificação das solicitações recebidas
Uso vcr.verifyAuth(token) para validar tokens nas solicitações recebidas:
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' });
}
});
Criação de tokens da Vonage
Uso vcr.createVonageToken(params) para gerar JWTs assinados para a autenticação na API da 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
});
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
exp | número | Sim | Prazo de validade do token como timestamp do Unix (segundos) |
aclPaths | Record<string, any> | Não | Restrições de caminho do ACL |
subject | sequência de caracteres | Não | Assunto do token (por exemplo, identificador do usuário) |
Métodos utilitários
vcr.getAppUrl()
Retorna a URL pública da instância do VCR em execução. Equivalente a ler o VCR_INSTANCE_PUBLIC_URL variável de ambiente.
const appUrl = vcr.getAppUrl();
// e.g. "https://my-app-dev.use1.runtime.vonage.cloud"
vcr.unsubscribe(id, provider?)
Para deixar de receber chamadas de retorno de uma assinatura de provedor:
const subId = await voice.onCall('onCall');
// Later, when you want to stop receiving calls:
await vcr.unsubscribe(subId, 'voice');
Estrutura típica de uma aplicação
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)
Importante: Sempre configure seu servidor para 0.0.0.0, não localhost ou 127.0.0.1. O VCR encaminha o tráfego de entrada por meio de um proxy interno, e o aplicativo não estará acessível se estiver escutando apenas na interface de loopback.