Introdução
Um modelo de IA pode ficar temporariamente indisponível, sobrecarregado ou receber uma entrada que não consegue entender. Um fallback fornece à aplicação uma alternativa planejada, em vez de retornar um erro imediatamente. Um fallback útil é limitado: ele tem uma lista curta e ordenada, além de um ponto claro de encerramento. Ele não deve tentar novamente indefinidamente nem chamar todos os modelos depois que o primeiro tiver sucesso.
Você implantará um pequeno Cloudflare Worker com dois caminhos. O caminho de fallback envia deliberadamente uma entrada no formato de chat para um modelo de embeddings, captura essa incompatibilidade previsível e, em seguida, chama um modelo de chat. O caminho saudável chama um modelo de chat primário compatível e para. Todas as tentativas passam pelo mesmo AI Gateway, portanto os logs mostram qual modelo falhou e qual modelo concluiu a solicitação.
Se você entrou diretamente neste curso, primeiro conclua Conecte o LabEx à sua conta da Cloudflare. Esse laboratório ensina a usar o terminal do LabEx, a autorização de dispositivo do Wrangler, a seleção da conta e o ID da conta. Conclua também Encaminhe a inferência por um gateway antes deste laboratório, pois este exercício se baseia nos conceitos de gateway e Workers AI apresentados nele.
O laboratório usa modelos do Workers AI hospedados pela Cloudflare e o binding do Workers AI. Ele não precisa do Workers Paid, de uma chave de provedor externo nem do Universal Endpoint descontinuado. A tentativa controlada com falha é rejeitada antes da inferência, e cada caminho bem-sucedido gera apenas uma resposta curta. Se a alocação diária compartilhada do Workers AI estiver indisponível, pare em vez de repetir as tentativas.
A configuração instala o Node.js 22.22.0 e o Wrangler 4.132.0 local do projeto em /home/labex/project/ai-gateway-fallback. Ela prepara verificações independentes, mas não autoriza o Wrangler, não cria recursos na nuvem, não implanta um Worker nem envia tráfego para modelos. O LabEx destrói a VM após o laboratório; mesmo assim, você deverá excluir o Worker remoto, o gateway e o token da API, pois destruir uma VM não remove recursos da nuvem.
Autorize a VM e nomeie o caminho de recuperação
Cada laboratório começa em uma VM nova. Nesta etapa, você autorizará o Wrangler a usar sua conta de aprendizado e salvará nomes exclusivos para um gateway, um Worker e um token temporário.
cd /home/labex/project/ai-gateway-fallback
npx wrangler --version
npx wrangler login --device --browser=false
Abra o link exibido, informe o código e autorize a conta de aprendizado desejada. O Wrangler solicitará as permissões de implantação do Worker e do Workers AI necessárias mais adiante neste laboratório; verifique a conta exibida antes de aprovar. Em seguida, consulte os dados estruturados de identidade:
npx wrangler whoami --json
Espere ver o Wrangler 4.132.0 e loggedIn: true. Substitua YOUR_ACCOUNT_ID pelo ID real de 32 caracteres mostrado para a conta desejada:
GATEWAY_ID="labex-c09-g05-$(openssl rand -hex 6)"
WORKER_NAME="${GATEWAY_ID/g05/g05-worker}"
TOKEN_NAME="$GATEWAY_ID-token"
cat > .labex/state.json <<JSON
{
"accountId": "YOUR_ACCOUNT_ID",
"gatewayId": "$GATEWAY_ID",
"workerName": "$WORKER_NAME",
"tokenName": "$TOKEN_NAME"
}
JSON
cat .labex/state.json
Esses identificadores não são segredos. Registrá-los faz com que as verificações e a limpeza posteriores tenham como alvo apenas os recursos deste laboratório.
Crie um AI Gateway observável
Nesta etapa, você criará o ponto de controle compartilhado que registra as duas rotas de modelo.
Um AI Gateway é um ponto de controle nomeado entre uma aplicação e as chamadas de modelos. Ele concentra os logs e metadados de várias tentativas, mesmo quando a aplicação muda de modelo.
Abra o Cloudflare Dashboard e escolha AI → AI Gateway → Create a custom gateway. Use o gatewayId salvo. Mantenha Collect Logs e Authenticated Gateway habilitados. Mantenha o cache, os limites de taxa, as tentativas e os limites de gastos desativados, e mantenha o faturamento do Workers AI em Standard. Em seguida, crie o gateway.

Abra My Profile → API Tokens, escolha Create Token → Create Custom Token e use o tokenName salvo. Adicione as permissões da conta AI Gateway — Edit e AI Gateway — Run, limitadas à conta de aprendizado desejada. Esse token temporário permite que o laboratório leia e depois exclua apenas o gateway dele; o binding de IA do Worker implantado não o incorpora.
Depois de criar o token, copie somente o valor após Bearer do comando de verificação de uso único da Cloudflare e armazene-o usando uma entrada oculta:
bash -c '
while :; do
read -ersp "Paste the AI Gateway token: " GATEWAY_TOKEN
printf "\n"
[ -n "$GATEWAY_TOKEN" ] && break
printf "Token cannot be empty; paste it again.\n" >&2
done
umask 077
printf "%s" "$GATEWAY_TOKEN" > .labex/gateway-token
unset GATEWAY_TOKEN
chmod 600 .labex/gateway-token
'
Leia novamente apenas as configurações importantes que não são secretas:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
> .labex/gateway.json
unset GATEWAY_TOKEN
node -e 'const g=require("./.labex/gateway.json").result; console.log({id:g.id,collect_logs:g.collect_logs,authentication:g.authentication})'
Espere ver o ID do gateway salvo, com os dois valores definidos como true.
Defina um Worker com duas tentativas
Nesta etapa, você escreverá a política de recuperação no código comum de um Worker. A política faz duas chamadas explícitas em vez de usar um loop, portanto o custo e a latência máximos ficam fáceis de visualizar.
A primeira chamada do caminho de fallback usa um modelo de embeddings. Modelos de embeddings transformam texto em vetores numéricos; eles não aceitam messages de chat. Fornecer uma entrada no formato de chat cria uma falha de compatibilidade segura e determinística antes da inferência. O bloco catch registra essa falha e faz uma chamada para um modelo de chat compatível.
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
WORKER_NAME=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).workerName')
cat > wrangler.jsonc <<JSON
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-09-17",
"ai": { "binding": "AI" }
}
JSON
cat > src/index.js <<JS
export default {
async fetch(request, env) {
const healthy = new URL(request.url).pathname === "/healthy";
const attempts = [];
const gateway = {
gateway: {
id: "$GATEWAY_ID",
metadata: {
lab: "g05-fallback",
mode: healthy ? "healthy" : "fallback",
synthetic: true
}
}
};
if (!healthy) {
try {
await env.AI.run(
"@cf/baai/bge-small-en-v1.5",
{ messages: [{ role: "user", content: "Reply with ROUTE OK" }] },
gateway
);
attempts.push({ model: "@cf/baai/bge-small-en-v1.5", status: "unexpected-success" });
} catch (error) {
attempts.push({
model: "@cf/baai/bge-small-en-v1.5",
status: "failed",
reason: String(error).slice(0, 180)
});
}
}
const selectedModel = healthy
? "@cf/meta/llama-3.3-70b-instruct-fp8-fast"
: "@cf/meta/llama-3.2-3b-instruct";
const result = await env.AI.run(
selectedModel,
{ prompt: "Reply with exactly: ROUTE OK", max_tokens: 12 },
gateway
);
attempts.push({ model: selectedModel, status: "succeeded" });
return Response.json({
mode: healthy ? "healthy-primary" : "fallback-recovery",
usedFallback: !healthy,
selectedModel,
attempts,
response: result.response
});
}
};
JS
npx wrangler deploy --dry-run
O binding de IA dá ao Worker acesso direto ao Workers AI. A opção gateway encaminha cada chamada pelo gateway salvo e adiciona apenas metadados sintéticos — nunca um prompt, uma credencial ou um identificador de pessoa.
Implante e exercite o caminho de fallback
Nesta etapa, você implantará o Worker e acionará uma vez o caso de recuperação controlada.
Implante o Worker e salve a saída do Wrangler para que o teste use a URL exata atribuída à sua conta:
npx wrangler deploy 2>&1 | tee .labex/deploy-output.txt
WORKER_URL=$(grep -Eo 'https://[^ ]+\.workers\.dev' .labex/deploy-output.txt | tail -1)
printf '%s\n' "$WORKER_URL" | tee .labex/worker-url.txt
A rota workers.dev pode levar alguns segundos para ser propagada após uma implantação bem-sucedida. Consulte a URL sem enviar tráfego adicional para modelos: um 404 indica apenas que a rota de borda ainda não está pronta, e o loop para na primeira resposta 200.
WORKER_URL=$(cat .labex/worker-url.txt)
for attempt in $(seq 1 12); do
STATUS=$(curl --http1.1 -sS -o .labex/fallback-response.json -w '%{http_code}' "$WORKER_URL/fallback")
printf 'attempt %s: HTTP %s\n' "$attempt" "$STATUS"
[ "$STATUS" = 200 ] && break
[ "$attempt" -eq 12 ] && exit 1
sleep 5
done
python3 -m json.tool < .labex/fallback-response.json
Espere ver usedFallback: true, duas tentativas, o modelo de embeddings marcado como failed e @cf/meta/llama-3.2-3b-instruct marcado como succeeded. O texto gerado não é avaliado exatamente; o que importa é a decisão de roteamento.
Comprove que um modelo primário saudável para cedo
Nesta etapa, você mostrará que um modelo primário bem-sucedido impede uma chamada de fallback desnecessária.
Um fallback só está correto se não interferir quando o caminho primário funciona. O caminho /healthy começa com um modelo de chat compatível, portanto deve produzir uma tentativa e parar.
WORKER_URL=$(cat .labex/worker-url.txt)
curl --http1.1 -fsS "$WORKER_URL/healthy" \
| tee .labex/healthy-response.json \
| python3 -m json.tool
Espere ver usedFallback: false, @cf/meta/llama-3.3-70b-instruct-fp8-fast como selectedModel e exatamente uma tentativa bem-sucedida. Esse é o comportamento de short-circuit: o sucesso encerra a rota imediatamente.
Leia a rota nos logs do gateway
Nesta etapa, você conectará os resultados JSON do Worker a evidências independentes do AI Gateway.
A resposta do Worker descreve o comportamento da aplicação. Os logs do AI Gateway fornecem evidências independentes do lado do provedor. Os logs podem levar alguns segundos para aparecer; aguarde brevemente e exiba apenas os campos relevantes para o roteamento:
sleep 8
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID/logs?per_page=50" \
> .labex/logs.json
unset GATEWAY_TOKEN
node - <<'NODE'
const rows=require('./.labex/logs.json').result||[];
const meta=row=>{try{return typeof row.metadata==='string'?JSON.parse(row.metadata):(row.metadata||{})}catch{return {}}};
console.table(rows.filter(row=>meta(row).lab==='g05-fallback').map(row=>({
mode:meta(row).mode, model:row.model, success:row.success, status:row.status_code
})));
NODE
Abra a página Logs do gateway no Dashboard. O grupo de fallback deverá conter uma linha do modelo de embeddings com falha e uma linha do modelo de fallback bem-sucedida. O grupo saudável deverá conter apenas o modelo de chat primário bem-sucedido.


Os metadados mode conectam as linhas sem incluir um prompt ou segredo. O modelo, o sucesso e o status explicam a rota; o texto gerado, por si só, não explica.
Inspecione o contrato de recuperação limitado
Nesta etapa, você comparará os dois caminhos e informará o número máximo de tentativas de modelo.
Agora você tem três formas correspondentes de evidência:
- o código-fonte contém duas chamadas explícitas a
env.AI.run()e nenhum loop de repetição; /fallbackinforma uma falha seguida de um sucesso;/healthyinforma um sucesso e para.
Exiba uma comparação compacta a partir das respostas salvas:
node - <<'NODE'
for (const name of ['fallback','healthy']) {
const body=require(`./.labex/${name}-response.json`);
console.log(name, {
usedFallback: body.usedFallback,
selectedModel: body.selectedModel,
attemptCount: body.attempts.length,
statuses: body.attempts.map(item=>item.status)
});
}
NODE
O máximo é de duas tentativas. Se o fallback também falhar, o Worker retornará um erro em vez de reiniciar a rota. Em uma aplicação de produção, você poderia adicionar um tempo limite, um disjuntor ou um erro amigável para o usuário, mas cada mecanismo de recuperação adicional deverá continuar limitado e observável de forma independente.
Remova os recursos descartáveis
Nesta etapa, você excluirá todos os recursos remotos pertencentes a este laboratório e removerá a autorização local.
Exclua primeiro o Worker para impedir que ele crie novo tráfego no gateway. Em seguida, exclua apenas o gateway registrado em state.json:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
WORKER_NAME=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).workerName')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
npx wrangler delete --name "$WORKER_NAME" --force
curl --http1.1 -fsS -X DELETE \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
> .labex/delete-gateway.json
unset GATEWAY_TOKEN
node -p 'require("./.labex/delete-gateway.json").success'
Espere ver true. Enquanto as duas autorizações temporárias ainda existirem nesta VM, salve evidências independentes da ausência do Worker e do gateway:
set +e
npx wrangler deployments list --name "$WORKER_NAME" --json \
> .labex/worker-after-delete.json 2> .labex/worker-absent.err
printf '%s\n' "$?" > .labex/worker-absent-status.txt
set -e
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways" \
> .labex/gateways-after-delete.json
unset GATEWAY_TOKEN
GATEWAY_ID="$GATEWAY_ID" node - <<'NODE'
const rows=require('./.labex/gateways-after-delete.json').result||[];
console.log('gateway absent:', !rows.some(row=>row.id===process.env.GATEWAY_ID));
NODE
grep -Ei '10090|10007|script_not_found|does not exist' .labex/worker-absent.err
Espere ver gateway absent: true e uma resposta indicando a ausência do Worker, como script_not_found, o código 10090, o código 10007 ou does not exist. O Wrangler pode usar formatos de erro diferentes para o mesmo script ausente; erros de rede e autenticação não comprovam a exclusão.
Agora abra My Profile → API Tokens e exclua exatamente o tokenName salvo. Por fim, remova a cópia dele na VM e encerre a sessão:
shred -u .labex/gateway-token
npx wrangler logout
npx wrangler whoami --json
Espere ver loggedIn: false. Excluir a VM posteriormente removerá os arquivos locais, mas somente esses comandos removem os recursos remotos e revogam a autorização.
Resumo
Você criou um caminho de recuperação limitado com dois modelos hospedados pela Cloudflare. Uma tentativa primária incompatível e controlada falhou, um modelo de fallback recuperou a solicitação e um modelo primário saudável parou após uma única chamada. Os logs do AI Gateway conectaram as decisões da aplicação às evidências do modelo e do status no lado do provedor. Você também aprendeu por que limites explícitos de tentativas, metadados seguros e uma limpeza verificada fazem parte de um design confiável de fallback.



