AI Connect/Como criar/Uma frota de agentes de IA
Uma frota de agentes de IA
Execute muitos agentes de IA autônomos a partir de uma única aplicação, modelando cada agente como um usuário próprio do AI Connect SDK, para que ele carregue apenas os conectores de que sua função precisa, com credenciais, gasto e revogação instantânea por agente. Nenhuma outra plataforma dá a cada agente de um enxame a própria identidade isolada.
A próxima plataforma que você vai construir não é um agente, é um enxame: um agente de triagem que lê tickets, um agente de pesquisa que obtém contexto, um agente de operações que executa runbooks, um agente de conformidade que bloqueia ações inseguras. Os sistemas de IA modernos já estão aí. O que nunca existiu é a infraestrutura para rodar esse enxame com segurança: até hoje, todo agente ou compartilhava as suas credenciais mestras, ou você construía um sistema de permissões à mão.
O AI Connect SDK dá a cada agente o que nenhuma plataforma jamais deu a um agente: a própria identidade como usuário, com conectores próprios, credenciais próprias, gasto próprio e botão de desligar próprio, apoiado em milhares de conexões de IA desde o primeiro dia. Dar a cada agente a união de todas as ferramentas é um risco de segurança e custo: o modelo se comporta de forma imprevisível, um loop descontrolado pode esgotar o orçamento, e você não consegue atribuir cada ação a um agente. A resposta usual da indústria é uma matriz de permissões enxertada numa conta compartilhada. O SDK resolve de um jeito que mais nada resolve, porque resolve do mesmo jeito que resolve humanos: cada agente é um usuário. Um external_id por agente, e o capabilities() retorna apenas aquilo que aquele agente tem direito de acessar. Um programa autônomo se torna um cidadão governado da sua plataforma. Essa frase nunca foi verdade para um produto de integração antes. É a diferença estrutural entre agentes que dividem o seu acesso e agentes que possuem o deles.
Os benefícios de "agente = usuário"
| Preocupação | Como "agente = usuário" resolve |
|---|---|
| Escopo | O external_id de cada agente conecta só os próprios conectores, o agente de triagem não executa pagerduty__page. |
| Custo | Cada conexão é medida e revogável pelo próprio token, então gasto e interrupção são por agente. |
| Auditoria | Você sempre sabe de qual agente é a ação que está olhando, pelo external_id. |
| Raio de impacto | Um agente descontrolado pode ser revogado com um único disconnect(), sem afetar os demais agentes. |
| Ciclo de vida | Crie um novo worker emitindo um novo id; desative-o desconectando. Sem deploy de configuração. |
Estes são agentes de IA, e eles por si só atuam como usuários do SDK. Não há humano no loop quando o ops-agent acessa sua ferramenta de incidentes às 03:00. O external_id opaco é exatamente o que permite que um ator não humano possua credenciais isoladas.
vinkius.user('alice_123').capabilities({ include: ['github'] })GET /apps/vk_app_xxx/users/alice_123/tools?connector=githubconst capabilities = await vinkius
.user('alice_123')
.capabilities({ include: ['github'] });CapabilitySet (6)
github__list_issues read-only
github__create_issue POST /repos/{owner}/{repo}/issues
github__list_pull_requests read-only
github__search_code read-only
...1. Dê a cada agente uma identidade estável
Derive o id do papel do agente e, se você escala workers, da instância. Prefixe para que um id de agente jamais colida com um humano ou departamento.
type AgentRole = 'triage' | 'research' | 'ops' | 'compliance';
const agentUserId = (role: AgentRole, instance = 'primary') =>
`agent-${role}-${instance}`;
// "agent-triage-primary", "agent-ops-worker-07"2. Defina o que cada agente pode conectar
Esse registro é a sua política de menor privilégio. Mantenha-a declarativa para raciocinar sobre a frota inteira de uma vez.
// server/fleet.ts
export const AGENTS: Record<AgentRole, { model: string; connectors: string[] }> = {
triage: { model: '[MODEL_ID]', connectors: ['zendesk', 'linear'] },
research: { model: '[MODEL_ID]', connectors: ['drive', 'confluence', 'search'] },
ops: { model: '[MODEL_ID]', connectors: ['pagerduty', 'kubernetes', 'github'] },
compliance: { model: '[MODEL_ID]', connectors: ['audit-log', 's3'] },
};3. Provisone um agente
No deploy, conecte as contas do agente. O ensure() marca o ator como agente para que seu painel de governança filtre a frota dos humanos.
import { vinkius } from './vinkius';
import { AGENTS, type AgentRole, agentUserId } from './fleet';
async function provisionAgent(role: AgentRole, instance = 'primary') {
const user = vinkius.user(agentUserId(role, instance));
await user.ensure({ kind: 'agent', role });
for (const slug of AGENTS[role].connectors) {
const connector = user.connector(slug);
await connector.connect();
// agentes headless não têm consentimento no navegador: forneça
// token/chave do seu cofre de segredos via connector.credentials.set()
}
return user.connectors(); // [{ slug, status }, …]
}Agentes rodam headless, então prefira conectores que aceitem token ou chave estática via credentials.set(). Conectores OAuth exigem consentimento humano ao menos uma vez, faça isso no onboarding e o agente reutiliza a conexão resultante.
4. Rode o loop de um agente
Cada agente carrega suas próprias capacidades com escopo. Ele não consegue ver as ferramentas de outro agente porque elas residem sob external_id diferentes.
// server/run-agent.ts
import OpenAI from 'openai';
import { vinkius } from './vinkius';
import { toOpenAITools, runOpenAIToolCall } from '@vinkius/connect/openai';
import { AGENTS, type AgentRole, agentUserId } from './fleet';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });
export async function runAgent(role: AgentRole, task: string, instance = 'primary') {
const user = vinkius.user(agentUserId(role, instance));
const capabilities = await user.capabilities({ include: AGENTS[role].connectors });
const messages: object[] = [
{ role: 'system', content: `Você é o agente ${role}. Conclua a tarefa usando apenas suas ferramentas.` },
{ role: 'user', content: task },
];
for (let step = 0; step < 12; step++) {
const completion = await openai.chat.completions.create({
model: AGENTS[role].model,
messages: messages as never,
tools: toOpenAITools(capabilities),
});
const msg = completion.choices[0].message;
messages.push(msg as object);
if (!msg.tool_calls?.length) return msg.content;
for (const call of msg.tool_calls) {
const result = await runOpenAIToolCall(capabilities, call);
messages.push({
role: 'tool',
tool_call_id: call.id,
content: JSON.stringify({ content: result.content, isError: result.isError }),
});
}
}
return 'Tarefa interrompida: orçamento de passos atingido.';
}5. Faça handoff entre agentes, preservando o escopo
Um agente de triagem escala para o de operações chamando-o com uma nova tarefa. O de operações roda sob seu próprio id e conecta suas próprias ferramentas, o handoff jamais amplia o que qualquer um dos dois pode fazer.
async function orchestrate(ticket: string) {
const triage = await runAgent('triage', `Classifique e roteie: ${ticket}`);
if (triage?.includes('INFRA')) {
// o agente ops usa pagerduty/kubernetes/github — tools que a triagem nunca vê
return runAgent('ops', `Mitigue: ${ticket}`);
}
return runAgent('research', `Reúna contexto sobre: ${ticket}`);
}Como o external_id é opaco, você pode escalar para fora: rode 20 workers de operações como agent-ops-worker-01 … agent-ops-worker-20. Cada um tem sua própria conexão e medição, então um loop descontrolado em um worker afeta apenas aquele worker.
6. O agente de conformidade / governador
Modele também um agente de política. Ele conecta ferramentas somente de leitura, inspeciona as ações de outro agente e pode desconectar um conector para revogar um agente, governança expressa como chamadas comuns do SDK.
async function quarantine(role: AgentRole, instance: string, slug: string) {
await vinkius.user(agentUserId(role, instance)).connector(slug).disconnect();
}7. Python ou CrewAI? Faça a ponte com JSON Schema neutro
O SDK é somente TypeScript hoje, mas as capacidades são portáveis. Em uma pilha Python, exponha o conjunto de ferramentas como dados pelo adapter neutro, ou chame diretamente o runtime da mesma conexão.
import { toJSONSchemaTools } from '@vinkius/connect/json-schema';
const definitions = toJSONSchemaTools(await vinkius.user('agent-ops-primary').capabilities());
// entregue `definitions` ao seu framework Python de agentes; ele chama de volta uma rota suaPor dentro: por que um único agente com comportamento anômalo não compromete a frota
O isolamento que você obtém sem escrever código não é apenas organizacional, ele é imposto pelo data plane, e é a verdadeira vantagem defensável de uma frota autônoma.
*Cada conexão possui o próprio token `vk_live_`.* A listagem e a execução de tools são roteadas diretamente ao runtime daquela conexão, onde cada chamada é medida e revogável pelo token dela*, jamais pela API da aplicação. Assim, o custo e a interrupção de um agente são independentes dos demais, por construção.
A revogação falha de forma fechada. O SDK emite exatamente um token por conexão no connect() e nunca o reemite implicitamente durante a execução. Isso significa que disconnect() encerra o acesso de imediato: um agente com token revogado não consegue emitir um novo automaticamente. Use-o como mecanismo de corte de emergência:
// o agente governador interrompe um worker com comportamento anômalo em uma chamada — de forma imediata e definitiva
await vinkius.user('agent-ops-worker-07').connector('pagerduty').disconnect();Limite cada passo. Um agente pode conceder a uma tool lenta mais tempo do que um humano concederia, mas você restringe cada chamada com timeoutMs (composto com um AbortSignal). Uma execução descontrolada passa a ter um prazo-limite, em vez de um orçamento ilimitado:
const result = await capabilities
.findCapability('kubernetes__scale_deployment')!
.execute(
{ deployment: 'ingress', replicas: 6 },
{ idempotencyKey: `ops:${task.id}:scale`, timeoutMs: 10_000 },
);Rastreie cada agente separadamente. Os hooks disparam por tentativa HTTP com um requestId já redigido, então você associa cada chamada, repetição e falha a um único external_id sem construir seu próprio sistema de tracing. Campos de credencial e o segmento de URL vk_live_* são mascarados antes de chegarem ao seu hook.
Transmita tipos, não texto livre. Quando um agente transmite dados a outro, prefira o result.structuredContent (o objeto estruturado devolvido pelo conector) a serializar o content: mais preciso, mais econômico em tokens e sem ambiguidade.
Checklist de produção
- [ ] Prefixe todo id de agente (
agent-…) para nunca colidir com humanos ou departamentos. - [ ] Expresse o menor privilégio no registro
AGENTS, um agente, um conjunto estreito de conectores. - [ ] Dê a agentes mutáveis um
idempotencyKeypor tarefa para que um loop repetido não execute duas vezes. - [ ] Defina um orçamento rígido de passos por loop de agente; devolva
isErrorao modelo em vez de lançar. - [ ] Marque atores com
user.ensure({ kind: 'agent', role })para a governança filtrar a frota. - [ ] Inclua
disconnect()no caminho do governador, a revogação de emergência é uma chamada por agente.
Você agora roda uma frota em que cada agente possui exatamente as ferramentas de que sua função precisa, o gasto de cada agente é independente e um agente descontrolado é neutralizado sem afetar os demais. A maioria dos times governa os próprios agentes com documentos de política e dedos cruzados. Você governa os seus com um sistema de identidades, e é essa distância que permite a sua frota crescer além de dez agentes enquanto a deles não cresce com segurança além de dois.
What you just got
Not a pitch: the properties this build inherits automatically.
Connections and capabilities resolve only inside one external_id. No cross-actor leakage is possible, and you wrote none of that enforcement.
Your server stores secrets and can read back which fields are configured, never the values. Not your code, the model, or a dashboard can exfiltrate them.
Every connection owns a vk_live_* token, so cost and revocation are per connection. One call to disconnect() is a complete, auditable stop.
One CapabilitySet converts to OpenAI, Anthropic, Gemini, Vercel AI SDK, LangChain, LlamaIndex, Workers AI or neutral JSON Schema. Only the last line changes.
idempotencyKey, timeoutMs and AbortSignal per call; automatic full-jitter retries on transient failures; typed VinkiusError branches. No bespoke harness.
Give each agent only its connectors, cap each loop with timeoutMs, revoke one misbehaving agent in one call. The others keep running.
Give it to your AI agent
An Agent Skill (SKILL.md) for this build. Preview the first lines below, then copy or download it into your repo under .claude/skills/: Claude Code, Cursor or any Agent-Skills-compatible agent follows it to implement this pattern correctly.
