bacp-protocol
v0.5.0
Published
BACP (Brazilian Agent Communication Protocol) — mini framework para comunicação entre agentes.
Maintainers
Readme
BACP
Brazilian Agent Communication Protocol — um mini framework em TypeScript (publicado como JS + tipos .d.ts) para padronizar como agentes conversam entre si, pensado com a comunidade brasileira em mente.
Menos gambiarra, mais contrato claro entre orquestrador e agentes.
Por que existe?
Quando você começa a encaixar vários “agentes” (analisador, coletor, notificador…) no mesmo fluxo, aparecem perguntas repetidas: qual o formato da mensagem? quem fala com quem? como correlacionar uma resposta ao pedido original?
O BACP reúne um protocolo de mensagem, um barramento simples e uma classe base de agente, para você focar na lógica de negócio e não reinventar o encaixe toda vez.
É propositalmente pequeno: dá para ler o código em uma tarde e adaptar ao seu projeto.
Instalação
Requer Node.js 18+ (ES modules).
npm install bacp-protocolO nome bacp sozinho costuma ser recusado no npm (similaridade com outros pacotes). Este projeto publica-se como bacp-protocol, neutro e alinhado ao propósito (protocolo BACP).
TypeScript
O pacote inclui definições de tipos (dist/*.d.ts). Em projetos TS:
npm install bacp-protocolimport {
createBus,
registerAgent,
type AgentMessage,
type BacpMiddleware,
} from "bacp-protocol";
const { ask } = createBus({
middleware: [
{
beforeHandle(msg: AgentMessage) {
console.log(msg.action);
},
},
],
});O código-fonte TypeScript está em src/; o artefato publicado no npm é a pasta dist/ (.js + .d.ts), gerada com npm run build antes do npm publish (ou ao desenvolver no pacote: cd bacp && npm install && npm run build). Quem instala o pacote pelo npm já recebe o dist pronto.
Modo simples (poucos comandos, estilo Node comum)
Ideias centrais: createBus() monta tudo; registerAgent(bus, id, ações) registra um agente com funções; ask manda tarefa (um agente responde); on / emit / once tratam eventos (vários ouvintes, sem destinatário único).
Tarefas (ask)
import { createBus, registerAgent } from "bacp-protocol";
const { bus, ask } = createBus();
registerAgent(bus, "meu-agente", {
saudar: (dados) => ({ texto: `Olá, ${dados.nome}!` }),
somar: (dados) => ({ total: dados.a + dados.b }),
});
const r1 = await ask("meu-agente", "saudar", { nome: "Maria" });
const r2 = await ask("meu-agente", "somar", { a: 2, b: 3 });Cada função em ações recebe (dados, mensagemCompleta) — na prática quase sempre só o primeiro argumento.
Eventos (on, emit, once)
Um evento usa type: "event" e destino reservado to: "*" (constante BROADCAST_TO). Vários handlers podem escutar o mesmo nome.
const { ask, on, once, emit } = createBus();
on("pedido.criado", (dados) => {
console.log("listener A", dados);
});
on("pedido.criado", (dados) => {
console.log("listener B", dados);
});
once("app.init", () => console.log("só uma vez"));
await emit("app.init", {});
await emit("pedido.criado", { id: 42 });Dentro de um agente, use agent.emit("nome", { ... }) para publicar com from correto. O emit do createBus usa o id do orquestrador como remetente.
Se já tiver um Orchestrator, pode usar orchestrator.ask(...) em vez de montar o objeto do dispatch.
Produção leve (sem infra extra)
metaenriquecido porcreateMessage:protocolVersion(constante exportadaPROTOCOL_VERSION, hoje"1") etraceId(por omissão igual arequestId, se você não passar outro).- Timeout ou cancelamento: quarto argumento de
ask/ opções emdispatch/bus.send:await ask("agente", "acao", {}, { timeoutMs: 5000 })await ask("agente", "acao", {}, { signal: controller.signal })
Em falha por tempo, o erro éBacpTimeoutError(também em cancelamento viaAbortSignal).
- Middleware no barramento:
bus.use({ async beforeHandle(msg) { ... }, async afterHandle(msg, result) { ... } })ou passecreateBus({ middleware: [ ... ] }). Erros emafterHandlesó geramconsole.warn, para não mascarar o resultado principal. - Utilitário
withTimeout(promise, { timeoutMs, signal })para qualquer Promise.
Fora do escopo deste pacote (roadmap / integrações à parte): filas distribuídas (Redis, SQS), métricas Prometheus, OpenTelemetry completo, auditoria persistente, autenticação por token entre processos.
Modo completo (classes e agentes prontos)
import BACP from "bacp-protocol";
const bus = new BACP.MessageBus();
const orchestrator = new BACP.Orchestrator({ bus });
new BACP.AnalyzerAgent({ bus });
new BACP.CollectorAgent({ bus });
const resultado = await orchestrator.dispatch({
to: "analyzer",
action: "analyze_products",
payload: { products: ["A", "B", "C"] },
});
console.log(resultado);Imports nomeados também funcionam:
import { MessageBus, Orchestrator, createMessage } from "bacp-protocol";Formato da mensagem
Toda troca segue um objeto com campos fixos — assim dá para logar, validar e evoluir sem quebrar o que já existe:
{
"type": "task",
"from": "orchestrator",
"to": "analyzer",
"action": "analyze_products",
"payload": {
"products": ["A", "B"]
},
"meta": {
"requestId": "123",
"timestamp": 1710000000,
"protocolVersion": "1",
"traceId": "123"
}
}type:task|response|eventfrom/to: ids dos agentes (o barramento usatopara rotear). Para eventos em broadcast, useto: "*"(BROADCAST_TO) — não use"*"como id de agenteaction: nome da operação que o destinatário implementapayload: dados da operação (objeto)meta: obrigatórios na validação:requestIdetimestamp. Em mensagens criadas comcreateMessage, também entram por defeitoprotocolVersionetraceId(pode sobrescrever emmeta)
O que vem no pacote
| Peça | Papel |
|------|--------|
| createBus / registerAgent | API mínima: ask, on, once, emit + registro por funções; createBus({ middleware }) |
| BROADCAST_TO / PROTOCOL_VERSION | Constantes do protocolo |
| BacpTimeoutError / withTimeout | Timeout e cancelamento |
| MessageBus | use(), agentes por id, send(msg, { timeoutMs, signal }) |
| Agent | handle, task(), respond(), emit() e mapa de ações |
| Orchestrator | dispatch(), ask() com timeout opcional; id padrão orchestrator |
| validateMessage / assertValidMessage / createMessage | Contrato e fábrica de mensagens |
| AnalyzerAgent / CollectorAgent | Exemplos prontos para copiar ou trocar |
Criar seu próprio agente
Sem classe — só funções:
import { createBus, registerAgent } from "bacp-protocol";
const { bus, ask } = createBus();
registerAgent(bus, "meu-agente", {
minha_acao: (dados) => ({ resultado: dados.valor * 2 }),
});Com classe (quando quiser herança ou organização maior):
import { Agent } from "bacp-protocol";
class MeuAgente extends Agent {
constructor(bus) {
super({
id: "meu-agente",
bus,
actions: {
minha_acao: (payload, message) => {
return { ok: true, recebido: payload };
},
},
});
}
}Estrutura do repositório (referência)
agent-framework/
├── core/
│ ├── Agent.js
│ ├── MessageBus.js
│ └── Orchestrator.js
├── protocol/
│ └── message.schema.js
├── agents/
│ ├── AnalyzerAgent.js
│ └── CollectorAgent.js
└── index.jsContribuindo
Ideias, issues e PRs são bem-vindos. Se algo não ficou claro na API, abre uma issue — melhor documentação também é contribuição.
Licença
MIT — use à vontade nos seus projetos.
Feito com cuidado para quem curte código legível e protocolos explícitos.
Se o BACP te ajudou, uma estrela no repositório já anima demais.
