AgentOffice é uma extensão Pi. O Pi runtime (pi-coding-agent) gerencia o loop de conversa, execução de ferramentas, autenticação com providers e streaming. AgentOffice adiciona a camada de orquestração: roteamento semântico, transporte entre equipes (coms-net ou NATS), portal em tempo real e protocolo A2A.
// AgentOffice como extensão Pi
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { createHub } from "./hub/index.js";
import { HybridScorer } from "./routing/hybrid.js";
import { startPortal } from "./portal/server.js";
export default function agentOffice(api: ExtensionAPI) {
const scorer = new HybridScorer(api.agents);
const hub = createHub(api, scorer);
// Ferramenta: enviar mensagem para outro agente
api.registerTool("send_message", async (args) => {
const target = await scorer.route(args.message);
return hub.dispatch(target.id, args.message);
});
// Comando: painel de controle da equipe
api.registerCommand("office", async (args) => {
return hub.status();
});
// Portal web na porta 3000
startPortal({ hub, port: 3000 });
}
O pipeline de roteamento combina recuperação esparsa e densa, fundindo os rankings com Reciprocal Rank Fusion. Zero configuração requerida — e reranking opcional com cross-encoder para máxima precisão.
Sparse retrieval por campo — título, tags e descrição ponderados individualmente.
Embeddings densos para similaridade semântica. Roda local, sem chamadas externas.
Reciprocal Rank Fusion — funde os dois rankings sem parâmetros de ajuste manual.
ms-marco-MiniLM reranking. Ativado via ROUTING_RERANK=true.
Para 1000+ agentes: ative via QDRANT_URL. O sistema migra automaticamente do HybridScorer em memória para o QdrantScorer, sem downtime e sem limite prático de vetores.
// SSE stream — conexão via GET /stream/:sessionId
event: routing:decision
data: {
"query": "preciso de ajuda com deploy no k8s",
"winner": {
"id": "devops-agent",
"score": 0.94,
"method":"hybrid"
},
"candidates": [
{ "id": "devops-agent", "bm25": 0.89, "embed": 0.91, "rrf": 0.94 },
{ "id": "backend-agent", "bm25": 0.61, "embed": 0.58, "rrf": 0.62 }
],
"latencyMs": 4,
"reranked": false
}
O portal web roda na porta 3000, a API REST na porta 3777. Ambos operam em paralelo — o portal consome a mesma API que você usa no seu código.
| MÉTODO | ENDPOINT | DESCRIÇÃO |
|---|---|---|
| GET | /agents | Lista agentes disponíveis com capacidades |
| POST | /message | Envia mensagem, retorna stream SSE |
| GET | /agents/:id/status | Estado atual do agente (idle / busy / error) |
| GET | /stream/:id | SSE stream de uma sessão ativa |
| POST | /team | Cria equipe de agentes com políticas de roteamento |
| GET | /teams | Lista equipes e membros ativos |
| DEL | /session/:id | Encerra sessão e libera recursos |
| GET | /routing/log | Histórico de decisões de roteamento |
| POST | /session | Abre nova sessão com agente específico |
| GET | /sessions | Lista sessões abertas por equipe |
| POST | /agents/:id/reload | Recarrega contexto e skills do agente |
| GET | /metrics | Métricas de roteamento, latência e throughput |
| PUT | /agents/:id/skills | Atualiza skills locais de um agente em runtime |
| POST | /chain | Executa uma chain multi-step entre agentes |
| GET | /schedules | Lista agendamentos ativos e próximas execuções |
| POST | /schedules | Cria agendamento com expressão cron |
| DEL | /schedules/:id | Remove agendamento |
| GET | /.well-known/agent.json | Agent Card do protocolo A2A |
Subir agent-office num Pi cria uma equipe. Qualquer agente dessa equipe pode, por sua vez, subir sua própria extensão agent-office e virar uma equipe própria — com seus próprios agentes, extensões e configurações. Sem limite de profundidade, sem limite de quantas equipes existem no ecossistema.
Três mecanismos, três papéis — não são camadas empilhadas, são alternativas para necessidades diferentes:
| MECANISMO | PAPEL | QUANDO USAR |
|---|---|---|
| coms-net hub | Transporte HTTP centralizado entre equipes/instâncias | Default — simples, sem infraestrutura de broker |
| NATS JetStream | Transporte pub/sub descentralizado entre equipes/instâncias | Alternativa ao coms-net — topologias maiores, at-least-once delivery |
| A2A Protocol | Interoperabilidade com agentes/frameworks fora do ecossistema Pi | Quando a outra ponta não fala o protocolo interno do AgentOffice |
PI_NATS_URL está configurado, o NATS assume descoberta e despacho entre equipes; sem ele, o coms-net hub HTTP cobre a mesma função como fallback. O roteamento semântico (messageRouter) decide quem responde independente de qual transporte estiver ativo por baixo.
Cada instância AgentOffice conecta ao cluster NATS ao iniciar. Peers são descobertos imediatamente — sem warm-up, sem registro manual. Mensagens persistem por 1 hora para garantia de entrega.
| SUBJECT | DIREÇÃO | FUNÇÃO |
|---|---|---|
| tasks.route | Pub | Nova tarefa enviada para roteamento |
| tasks.result | Sub | Resultado final da execução do agente |
| tasks.stream | Sub | Streaming incremental de resultado (chunks) |
| tasks.cancel | Pub | Cancelamento de tarefa em andamento |
| agents.ping | Pub/Sub | Descoberta de peers — emitido imediatamente ao conectar |
| agents.capabilities | Sub | Capacidades anunciadas por peers remotos |
Credenciais .creds por agente — isolamento de identidade e permissões granulares no cluster.
PI_NATS_URL=nats://cluster:4222
NATS_CREDS_DEVOPS=./creds/devops.creds
NATS_CREDS_BUILDER=./creds/builder.creds
Token único para todos os agentes — ideal para ambientes de desenvolvimento e teste locais.
PI_NATS_URL=nats://localhost:4222
PI_NATS_TOKEN=meu-token-secreto
Cada agente é construído a partir de camadas de contexto com prioridade definida. Camadas de menor número têm precedência — o AGENTS.md define quem faz o quê, o SOUL.md persiste a personalidade.
| PRIO | ARQUIVO | FUNÇÃO |
|---|---|---|
| 10 | AGENTS.md | Definição dos agentes e roteamento |
| 20 | SOUL.md | Traços de personalidade persistentes |
| 30 | IDENTITY.md | Função e especialização do agente |
| 40 | USER.md | Preferências e histórico do usuário |
| 50 | TOOLS.md | Ferramentas disponíveis e instruções |
| 60 | skills globais | Capacidades compartilhadas entre agentes |
| 70 | skills locais | Capacidades exclusivas do agente |
# Skills disponíveis para os agentes
extensions/skills/
├── global/ ← disponível para todos
│ ├── code-review.md
│ ├── git-workflow.md
│ └── security-check.md
└── agents/
├── devops/ ← exclusivo do agente devops
│ ├── deploy.md
│ └── k8s-debug.md
└── builder/ ← exclusivo do agente builder
├── scaffold.md
└── test-runner.md
Qualquer agente externo compatível com A2A pode descobrir e interagir com o AgentOffice — e vice-versa. O handshake começa via Agent Card pública em /.well-known/agent.json.
tasks/send
Envia uma tarefa e aguarda resposta completa. Bloqueante — ideal para tarefas curtas ou quando o resultado é necessário imediatamente.
tasks/sendSubscribe
Envia e recebe resultado como SSE stream. Ideal para tarefas longas — o agente emite chunks conforme processa.
tasks/get
Consulta estado de uma tarefa assíncrona pelo ID. Use com tasks/send em modo non-blocking.
tasks/cancel
Cancela uma tarefa em execução. O agente recebe o sinal de cancelamento e libera recursos — consistente com o sinal NATS tasks.cancel.
{
"name": "AgentOffice Hub",
"description": "Multi-agent orchestration platform built on Pi runtime",
"url": "https://ao.platformteam.dev",
"version": "1.0.0",
"capabilities": {
"streaming": true,
"pushNotifications": false,
"stateTransitionHistory": true
},
"skills": [
{
"id": "route-message",
"name": "Route Message",
"description": "Route a message to the best-matched agent via HybridScorer",
"tags": ["routing", "multi-agent", "nlp"]
}
]
}
Chains encadeiam passos entre agentes diferentes com interpolação de resultados. Schedules ativam chains ou mensagens avulsas em horários definidos por expressão cron.
Cada step envia uma mensagem a um agente e captura o resultado. O resultado de um step fica disponível como {{stepN.result}} nos steps seguintes.
name: code-review-pipeline
steps:
- id: fetch-diff
agent: devops
message: "Gere o diff da PR #{{input.pr_number}}"
- id: review-code
agent: reviewer
message: |
Revise o diff abaixo e aponte issues:
{{fetch-diff.result}}
- id: write-comment
agent: github-bot
message: "Poste no PR: {{review-code.result}}"
Além de result, você pode acessar status, agentId e latencyMs de cada step.
Agendamentos usam expressões cron padrão e suportam timezone. Podem acionar chains completas ou mensagens avulsas para agentes específicos.
name: daily-standup-report
cron: "0 9 * * 1-5" # seg–sex às 9h
timezone: America/Sao_Paulo
chain: standup-pipeline
input:
channel: general
format: markdown
---
name: security-scan
cron: "0 2 * * *" # toda madrugada às 2h
timezone: UTC
agent: security
message: "Execute scan completo e envie relatório"
Se o servidor estiver offline no horário agendado, a execução é ignorada — não há catch-up automático. Use o NATS para durabilidade em setups distribuídos.