Agentes e ferramentas
Adicione um agente
Um agente é um objeto simples. Crie agents/src/agents/support.ts:
import type { AgentSpec } from '@rubrion/mastra-cloudflare';
export const support: AgentSpec = {
id: 'support',
name: 'Suporte',
// O roteador "auto" escolhe agentes por esta linha: diga para que o agente serve.
description: 'Responde dúvidas sobre o nosso produto, planos e cobrança.',
instructions: `Você é o nosso agente de suporte. Seja breve e gentil.
Se não souber, diga isso e ofereça a página de contato.`,
maxOutputTokens: 800,
};
Liste-o em agents/src/index.ts:
export const agents = defineAgents([writer, researcher, support], { memory });
Ele aparece em /v1/models, na página de configurações (onde você pode desligá-lo) e no roteamento auto.
:::tip Escreva a descrição para o roteador
O roteamento auto lê apenas as descriptions dos agentes. Diga para que o agente serve e o tipo de pedido que ele atende ("Responde dúvidas sobre planos e cobrança"), não como ele funciona.
:::
Adicione uma ferramenta
Ferramentas são ferramentas do Mastra: um id, uma descrição que o modelo lê, um schema de entrada e uma função.
import { createTool, z } from '@rubrion/mastra-cloudflare';
import { env } from 'cloudflare:workers';
export const lookupOrder = createTool({
id: 'lookup_order',
description: 'Status de um pedido pelo número.',
inputSchema: z.object({ order: z.string() }),
execute: async ({ order }) => {
const res = await fetch(`https://api.example.com/orders/${order}`, {
headers: { authorization: `Bearer ${env.ORDERS_TOKEN}` },
});
return res.ok ? res.json() : { error: `HTTP ${res.status}` };
},
});
Entregue-a a um agente: tools: { lookup_order: lookupOrder }, e mencione-a nas instruções do agente ("Use lookup_order para o status de pedidos").
Um segredo de que a ferramenta precisa fica no Worker de agentes, nunca num prompt:
cd agents && npx wrangler secret put ORDERS_TOKEN
Localmente, coloque-o em agents/.dev.vars. Declare-o em agents/src/env.d.ts para o TypeScript conhecê-lo (em Cloudflare.Env, o tipo do env de cloudflare:workers):
declare namespace Cloudflare {
interface Env {
ORDERS_TOKEN: string;
}
}
Modelos
Cada agente usa, nesta ordem:
- seu próprio
model, quando tem um; - o provedor definido na página de configurações (qualquer endpoint compatível com OpenAI);
- o modelo embutido do Workers AI,
DEFAULT_MODELemagents/src/index.ts(Gemma 4). Ele precisa suportar chamadas de ferramentas.
Um agente com seu próprio modelo:
import { openAICompatible, workersAI } from '@rubrion/mastra-cloudflare';
import { env } from 'cloudflare:workers';
export const coder: AgentSpec = {
id: 'coder',
name: 'Coder',
description: 'Escreve e revisa código.',
instructions: 'Você escreve código correto e idiomático. Explique brevemente.',
model: () => openAICompatible({ baseURL: 'https://openrouter.ai/api/v1', apiKey: env.OPENROUTER_KEY, model: 'qwen/qwen3-coder' }),
// ou, no Workers AI com o raciocínio ligado:
// model: () => workersAI(env.AI, '@cf/qwen/qwen3-30b-a3b-fp8', { thinking: true }),
};
Roteamento
Com model: "auto", um planejador (no mesmo provedor) lê as descrições dos agentes e as últimas mensagens, e decide quem responde a última mensagem:
- um agente, quando isso basta (na maioria das vezes);
- até três agentes para entregas claramente distintas ("resuma esta página e escreva um tweet"). Cada um recebe só a sua parte, e as respostas são juntadas sob os nomes deles.
Se o planejador falhar, o primeiro agente responde. Para desligar o roteamento, passe planner: false para createAgentServer em agents/src/index.ts; aí os clientes escolhem o agente pelo nome.
Memória
Os clientes enviam a conversa em messages, então os agentes não guardam estado por padrão: é assim que o rubry.ai, o Open WebUI e o SDK da OpenAI funcionam.
Um cliente pode, em vez disso, enviar o cabeçalho X-Session-Id. Aí só a mensagem nova é necessária: o agente recupera as últimas mensagens da sessão no D1 (o binding MEMORY), por agente. Mude quantas com lastMessages em agents/src/index.ts.