Agentes

Define um agente a partir de um prompt, um modelo e um conjunto de ferramentas, e deixa o runtime chamar o modelo, executar ferramentas e repetir o ciclo até chegar a uma resposta.

O que é um agente

Um agente é uma definição pequena e declarativa. Tem um nome, um system prompt que lhe dá uma personalidade, uma ligação de modelo com a qual raciocinar e uma lista de ferramentas que tem permissão para chamar. Um punhado de opções extra (um limite de iterações, uma temperatura, com quem pode falar, quem pode administrar) completam o conjunto. É tudo. O agente não guarda lógica própria. O runtime do Pepe faz o trabalho: chama o modelo, executa as ferramentas que o modelo pedir, devolve os resultados e repete até haver uma resposta final.

Cada agente vive como uma entrada dentro de um único ficheiro JSON em ~/.pepe/config.json. Não há base de dados. Podes criar e editar agentes de três formas, e todas escrevem no mesmo ficheiro:

  1. A ferramenta de linha de comandos pepe.
  2. O painel web.
  3. Uma conversa normal, falando com um agente que tenha a ferramenta de gestão correspondente.

Eis um agente completo tal como fica em disco:

{
  "agents": {
    "assistant": {
      "description": "General-purpose helper",
      "model": "openrouter",
      "system_prompt": "És um assistente prestável e direto.",
      "tools": ["bash", "read_file", "write_file", "web_search"],
      "auto_approve": [],
      "can_message": [],
      "can_manage": null,
      "hooks": [],
      "max_iterations": 12,
      "temperature": null
    }
  }
}

O teu primeiro agente

Um agente precisa de uma ligação de modelo antes de conseguir raciocinar. Se ainda não criaste nenhuma, a configuração guiada acompanha-te para escolher um fornecedor, iniciar sessão e escolher um modelo:

pepe setup

Depois define um agente com um prompt e algumas ferramentas:

pepe agent add assistant \
  --model openrouter \
  --prompt "És um assistente prestável e direto." \
  --tools bash,read_file,write_file,web_search

Corre um prompt de uma só vez contra ele. A resposta é transmitida para o teu terminal à medida que é produzida:

pepe run assistant "Que ficheiros existem no diretório atual?"

Esse único comando dispara o ciclo completo. O agente decide que precisa de olhar para o sistema de ficheiros, chama a ferramenta list_dir ou bash, lê o resultado e responde-te em linguagem natural.

A partir do painel. A secção de Agentes do painel web faz o mesmo com um formulário: nome, personalidade, modelo, uma lista de seleção de ferramentas e o âmbito de administração. Escreve a mesma entrada em ~/.pepe/config.json, por isso podes combinar livremente a CLI, o painel e a edição manual.

Fá-lo pela conversa

Qualquer agente que tenha a ferramenta manage_agent pode criar e configurar outros agentes por conversa. É assim que o primeiríssimo agente (vê “O agente proprietário” mais abaixo) te deixa construir o resto da tua frota sem tocar na CLI. Uma mensagem como:

Cria um agente chamado researcher. Dá-lhe uma persona focada em pesquisa
cuidadosa na web, aponta-o ao modelo openrouter e ativa web_search e
fetch_url.

O agente chama manage_agent com action: "create", e depois set_persona, set_model e add_tool para cada capacidade. manage_agent é uma ferramenta de risco: passa pela barreira de permissão, por isso numa superfície que consegue perguntar (a consola, um canal de chat) o runtime pede-te para autorizar a alteração antes de a escrever, e a própria ferramenta é instruída a confirmar o plano contigo primeiro. Um agente só pode gerir os agentes dentro do seu âmbito can_manage (tratado em Administrar agentes mais abaixo); pedir-lhe para mexer num que esteja fora desse âmbito é recusado com cortesia.

Os campos, um a um

Campo O que faz Predefinição
name A identidade do agente, e a chave sob a qual é guardado e endereçado. Dentro de um projeto passa a ser um identificador como acme/assistant (vê abaixo). obrigatório
description Uma nota curta para humanos. Nunca enviada ao modelo. nenhum
model O nome de uma ligação de modelo. Deixa por definir para usar o modelo predefinido do âmbito. predefinição do âmbito
system_prompt A personalidade e as instruções com que o agente corre. És o Pepe, um agente de IA prestável. (um prompt inicial)
langfuse_prompt Vai buscar a persona ao prompt com esse nome no Langfuse em vez do system_prompt. null (desligado)
tools A lista de nomes de ferramentas que este agente pode chamar. Só estas são oferecidas ao modelo. todas as ferramentas - um agente novo já nasce com tudo ativado; retiras o que não quiseres
auto_approve Ferramentas que este agente pode executar sem pedir permissão. ["*"] significa todas. []
can_message Outros agentes aos quais este pode enviar mensagens (uma rota dirigida). []
can_manage Que agentes este pode administrar. Vê Administrar agentes. null (só a si próprio)
hooks Transformações do fluxo de mensagens a aplicar, como a redação de dados pessoais. []
max_iterations O limite máximo de quantas rondas de modelo mais ferramenta um turno pode ter. 12
temperature Temperatura de amostragem passada ao modelo. Por definir usa a predefinição do próprio fornecedor. predefinição do fornecedor
triage_model Uma ligação de modelo que julga a complexidade antes do primeiro turno de uma sessão. Vê Encaminhamento de modelo por complexidade. nenhum (desligado)
simple_model A ligação de modelo para a qual desce quando triage_model julga uma conversa simples. nenhum

Como corre o ciclo de chamada de ferramentas

Quando envias um turno a um agente, o runtime faz o seguinte:

  1. Chama o modelo com a conversa até ao momento e as especificações JSON de cada ferramenta na lista permitida do agente.
  2. Se o modelo responder com uma resposta final, essa resposta é devolvida e o ciclo termina.
  3. Se em vez disso o modelo pedir para chamar uma ou mais ferramentas, o runtime executa cada uma, acrescenta os resultados à conversa e volta ao passo 1.
  4. Isto repete-se até o modelo produzir uma resposta final ou o ciclo atingir max_iterations. Se o limite for atingido, o turno termina com a nota (stopped: max iterations reached).

Como os resultados são devolvidos ao modelo, ele pode encadear passos. Pode ler um ficheiro, decidir que precisa de outro, ler esse também e depois escrever um resumo, tudo dentro de um mesmo turno. O limite de iterações é a salvaguarda que impede que um agente confuso ande em ciclo para sempre.

Outras duas barreiras ficam à frente da chamada ao modelo. Um agente cujo modelo exige redação recusa-se a correr a menos que o agente tenha um hook de redação ativado, e um projeto que atingiu o seu limite de gasto mensal (ou o seu limite de mensagens de clientes por mês, um limite separado) para aqui sem novas chamadas ao modelo nem respostas. Ambas falham o turno de forma limpa em vez de prosseguir em silêncio; ver Faturação e limites para saber como configurar esses limites.

Transmissão e eventos. À medida que o ciclo corre, emite eventos de ciclo de vida: um fragmento de texto transmitido (assistant_delta), uma mensagem completa do assistente (assistant), uma chamada de ferramenta (tool_call), uma ferramenta recusada (tool_denied), um resultado de ferramenta (tool_result), uma troca para um modelo de fallback (failover), um registo de uso de tokens (usage), uma resposta final (done) ou um erro (error). A CLI, o WebSocket e os canais de mensagens mostram tudo ao vivo, e é por isso que vês a escrita e a atividade das ferramentas à medida que acontece, em vez de um único bloco no fim.

Conversas longas: compactação

Uma conversa não cresce para sempre dentro da janela de contexto do modelo. Quando o tamanho estimado ultrapassa cerca de 60% dela, o runtime substitui o meio do histórico por um resumo curto que o próprio modelo escreve, mantendo o system prompt e os turnos mais recentes tal como estão. Isto é automático e não precisa de configuração - a transcrição completa continua guardada (vê Traces), só o que é enviado ao modelo é condensado.

Por defeito, esse resumo acontece uma vez, do zero, sempre que o limiar é ultrapassado de novo - suficiente para a maioria das conversas, mas uma que dure muito pode atingi-lo repetidamente, resumindo de cada vez um meio que só ficou maior. Um agente pode optar pelo micro_compaction em vez disso: quando a janela enche, dobra exatamente a troca mais antiga ainda não coberta num resumo contínuo a cada turno, um custo pequeno e constante em vez de uma paragem periódica. A contrapartida é real, por isso vem desligado por defeito: o resumo contínuo muda a cada turno assim que ativo, o que custa parte da estabilidade da cache de prompt de um fornecedor - vale a pena para uma conversa suficientemente longa para atingir o limiar com frequência, não para uma curta.

pepe agent add support --micro-compaction ...

Ou liga-o num agente existente a partir do editor de agentes do painel, ou pede a um agente com a tool manage_agent para ligar o interruptor micro_compaction noutro agente.

Mencionar o que mais sabe fazer

Quem já usa um agente para uma coisa muitas vezes nunca descobre que ele também consegue vigiar algo por alterações, correr uma tarefa recorrente, ou trabalhar por um objetivo até este estar mesmo concluído - nada mostra isso além do que a própria persona do agente eventualmente mencione. O capability_nudge, desligado por defeito, deixa o agente acrescentar uma frase curta e natural a apontar uma funcionalidade relacionada logo depois de ajudar com algo, quando esta realmente se aplica - não é um menu, nem em todos os turnos. Descoberta pelo uso, não uma avalanche de onboarding.

pepe agent add support --capability-nudge ...

Deixa desligado num agente que deve manter-se direto e transacional; liga-o a partir do editor de agentes do painel, ou pede a um agente com a tool manage_agent para ligar o interruptor capability_nudge noutro agente.

Ferramentas e a barreira de permissão

Uma ferramenta é uma capacidade. Um agente só pode fazer aquilo que a sua lista tools permite. Dá a um agente read_file mas não write_file e ele consegue olhar mas não mexer.

Lista todas as ferramentas disponíveis na tua instalação:

pepe tools

O conjunto integrado cobre o essencial:

Ferramenta O que faz
bash Executa um comando de shell.
run_script Escreve e executa um programa curto em Python, Node, Ruby ou Elixir.
read_file, write_file, edit_file, move_file, list_dir Trabalha com ficheiros no workspace do agente.
fetch_url, web_search Lê uma página web ou pesquisa na web.
send_file Entrega um ficheiro que o agente produziu no canal atual.
send_to_agent Envia mensagem a outro agente (sujeito a can_message).
ask_user Pede-te para escolheres entre algumas opções, com botões/menu reais onde o canal o permite.
schedule_task, watch Cria tarefas recorrentes e vigias de uma só vez do tipo “avisa-me quando X”.
manage_agent, rename_agent, enable_tool, set_route Gere agentes, ferramentas e encaminhamento pelo chat.
manage_channel, end_session Liga e fecha canais de mensagens pelo chat.
manage_mcp, scan_skill, skill Adiciona servidores de ferramentas externas e competências.
manage_plugin Instala, verifica, lista e remove plugins da comunidade (ferramentas, canais) pelo chat.
config_get, config_set, doctor Inspeciona e altera a configuração sob salvaguardas, corre diagnósticos.

Algumas ferramentas são só de leitura e correm livremente: read_file, list_dir, fetch_url, web_search, config_get, skill, docs, doctor, scan_skill e send_to_agent (que é regida pela lista de rotas permitidas can_message). Todo o resto, incluindo qualquer ferramenta de plugin, é tratado como de risco e passa por uma barreira de permissão antes de executar.

Quando uma ferramenta de risco não foi pré-aprovada e a superfície consegue perguntar a uma pessoa (a consola, um canal de chat), o runtime pede-te para autorizar a chamada. Podes responder:

Coloca tu próprio uma ferramenta em auto_approve para saltar o aviso desde o início. Em superfícies sem pessoa a quem perguntar (por exemplo a API HTTP, um webhook, uma tarefa cron), uma ferramenta com barreira é recusada em vez de correr sem supervisão: só corre o que já está em auto_approve.

A pedir-te para escolheres

Algumas perguntas respondem-se melhor com um toque do que com uma resposta escrita. O ask_user permite a um agente apresentar uma pergunta de escolha múltipla genuína e receber a escolha de volta dentro do mesmo turno, em vez de adivinhar ou terminar o turno à espera que a mensagem seguinte responda exatamente ao que foi perguntado. No Telegram aparece como botões inline reais; na consola, como um menu numerado; no chat do painel, como opções clicáveis. Corre livremente (perguntar não tem risco nenhum, por isso nunca passa pela barreira de permissões), mas só funciona onde há uma pessoa interativa a quem perguntar: a API HTTP, um webhook ou uma execução não supervisionada de cron/watch recusam a chamada de imediato, em vez de ficarem à espera de um botão que ninguém pode carregar.

Fá-lo pela conversa

Um agente que acabou de instalar um plugin, ou que quer uma capacidade que ainda não tem, pode ativar uma ferramenta em si próprio com enable_tool:

Enable the web_search tool for yourself.

O agente chama enable_tool com o nome da ferramenta. A ferramenta já tem de existir como integrada ou como plugin instalado, e a alteração entra em vigor na próxima mensagem do agente. enable_tool tem barreira também, por isso autorizas a concessão antes de ser escrita.

A ligação de modelo

model nomeia uma ligação que definiste com pepe model add. Deixá-la por definir significa que o agente usa o modelo predefinido do seu âmbito, por isso podes apontar um conjunto inteiro de agentes para um fornecedor e trocá-los todos ao mudar uma única predefinição.

Uma ligação de modelo pode transportar uma cadeia de fallback. Quando o modelo primário do agente falha com um erro transitório (um limite de taxa, um tempo esgotado, uma quebra de rede ou um 5xx), o runtime desce pela cadeia e volta a tentar no modelo seguinte, emitindo um evento failover enquanto o faz. Um erro grave como uma chave de API errada ou um pedido mal formado falha de imediato, já que outro endpoint não o resolveria.

O Pepe fala com os fornecedores através do protocolo Chat Completions da OpenAI, por isso qualquer endpoint compatível com OpenAI funciona sem alteração de código.

Fá-lo pela conversa

Um agente com a ferramenta manage_agent pode reapontar um modelo que administra:

Point the researcher agent at the groq-fast model.

O agente chama manage_agent com action: "set_model". O modelo de destino tem de ser uma ligação configurada, e a alteração passa pela barreira de permissão como qualquer outra edição de configuração.

Encaminhamento de modelo por complexidade

O próprio model de um agente é tratado como a boa predefinição. Opcionalmente, uma chamada de classificação barata e direta pode julgar se uma conversa é simples o suficiente para descer para algo mais barato, antes mesmo de o turno a sério começar. Sem agente extra para configurar, só dois campos:

pepe agent add assistant \
  --model modelo-forte-e-caro \
  --triage-model modelo-barato-e-rapido \
  --simple-model modelo-do-dia-a-dia \
  --prompt "..." \
  --tools bash,read_file,web_search

A triagem corre uma única vez, no primeiro turno de uma sessão, nunca mais naquela mesma sessão. Assim que uma conversa é julgada simples, fica no modelo mais barato durante o resto da conversa (o mesmo mecanismo que o comando /model usa para mudar o modelo de uma sessão, só que acionado automaticamente em vez de à mão). Um veredito complexo não muda nada: a sessão corre no próprio modelo do agente exatamente como correria sem triage_model definido.

A triagem é uma otimização de melhor esforço, nunca uma dependência. Se o modelo de triagem não existe, está inacessível, ou demora demasiado tempo (com um limite de poucos segundos), o turno segue no próprio modelo do agente, em silêncio. Uma falha na triagem nunca bloqueia nem quebra uma conversa. simple_model também precisa de estar definido para a triagem correr; senão não haveria para onde descer.

Cada veredito aparece como um passo próprio no Trace desse turno (o replay de cada execução no painel), junto de qualquer hook de privacidade que tenha corrido sobre a mensagem. Assim vês exatamente porque é que uma sessão acabou num modelo e não noutro.

O agente predefinido

Um agente por âmbito pode ser o predefinido. O predefinido é o que corre quando não nomeias um agente:

pepe run "resume este repositório"

O primeiro agente que crias no projeto default torna-se automaticamente o predefinido. Muda-o quando quiseres:

pepe agent default assistant

O agente proprietário

O primeiríssimo agente criado durante a configuração é o agente do próprio proprietário, e nasce plenamente capaz. Recebe todas as ferramentas, é superadministrador sobre todos os outros agentes (can_manage é ["*"]) e todas as suas chamadas de ferramenta vêm pré-aprovadas (auto_approve é ["*"]) para que nunca pare para perguntar. É isto que te deixa fazer trabalho a sério pela conversa desde o primeiro minuto, incluindo criar e configurar todos os agentes seguintes. Os agentes que adicionas depois são mais restritos por predefinição: escolhes as suas ferramentas, administram apenas a si próprios e as suas chamadas de risco passam pela barreira de permissão.

Deixar os agentes falarem entre si

can_message é uma lista de rotas permitidas dirigida. Se o agente A inclui o agente B, então A pode enviar a B uma mensagem com a ferramenta send_to_agent. O contrário não está implícito. Adiciona uma rota pela CLI:

pepe agent route triage assistant

Agora triage pode passar trabalho a assistant. Remove a rota com --remove. As rotas nunca cruzam a fronteira de um projeto; a CLI recusa A -> B quando os dois estão em projetos diferentes.

Fá-lo pela conversa

Um agente com a ferramenta set_route pode mudar o encaminhamento por conversa. from assume por predefinição o agente que está a chamar:

Allow yourself to message the billing agent.

O agente chama set_route com action: "allow" e to: "billing". O encaminhamento é dirigido, por isso isto não deixa billing responder com mensagens. Por editar a configuração, set_route passa pela barreira de permissão e tu autorizas a alteração.

Administrar agentes

can_manage controla que agentes um agente pode administrar (criar, editar, reconfigurar, treinar) através da ferramenta manage_agent. É fechado por predefinição e o seu significado é preciso:

Concede autoridade de gestão diretamente:

pepe agent manage supervisor "*"

Fá-lo pela conversa

Um agente administrador usa manage_agent para moldar os agentes do seu âmbito. As suas ações são list, get, create, set_persona, set_model, add_tool, remove_tool e remember (acrescenta um facto duradouro à memória do alvo). Por exemplo:

Dá ao agente de apoio a ferramenta send_file e regista na memória dele que
reembolsos acima de 200 precisam de uma pessoa.

O agente chama manage_agent com action: "add_tool" e depois com action: "remember". Cada uma destas ações tem barreira: o agente propõe a alteração, tu autoriza-la e só então é aplicada. Um agente também se pode renomear com a ferramenta separada rename_agent (“De agora em diante, chama-te scout”), que move o diretório do seu workspace e entra em vigor na próxima mensagem.

Agentes multi-tenant com projetos

Todo o tenant é um projeto. Uma instalação single-tenant vive inteira no projeto default (slug default), aquele para o qual cada comando recorre por omissão, e funciona exatamente como sempre funcionou. Adiciona um projeto para isolar um cliente: os seus agentes, espaços de trabalho, espaço partilhado, ligações de modelo e encaminhamento ficam isolados de qualquer outro projeto.

A identidade real de um agente é o seu identificador. No projeto default o identificador é apenas o nome simples (assistant). Dentro de outro projeto é qualificado como projeto/nome (acme/assistant), por isso o mesmo nome simples pode ser reutilizado entre projetos sem colisão. Por baixo desse identificador, cada agente guarda um id interno estável: renomeá-lo troca apenas o rótulo e move o diretório do workspace, e toda a referência (rotas, gestão, tokens) segue pelo id.

Cria um projeto e depois adiciona agentes dentro dele com --project:

pepe project add acme --description "Acme Corp"

pepe agent add support \
  --project acme \
  --model openrouter \
  --prompt "És o agente de apoio da Acme." \
  --tools read_file,web_search

Adiciona --project acme a qualquer comando de agente para agir dentro desse âmbito. Nomes de pares simples em --can-message e --can-manage resolvem-se dentro do próprio projeto do agente, por isso as rotas nunca cruzam por acidente a fronteira de um projeto. Cada projeto pode fixar o seu próprio modelo predefinido e o seu agente predefinido, ou partilhar o fornecedor global do operador. Um agente de um projeto nunca é promovido a predefinido global só por ser o primeiro criado dentro do seu projeto.

Gerir agentes pela CLI

# Cria um agente. Omite --tools para conceder todas as ferramentas; passa --tools "" para nenhuma.
pepe agent add NAME \
  --model MODEL \
  --prompt "..." \
  --tools t1,t2 \
  [--description "..."] \
  [--can-message b,c] \
  [--can-manage x,y | "*" | none] \
  [--hooks pii_redact] \
  [--max-iterations 12] \
  [--temperature 0.7] \
  [--triage-model MODEL] \
  [--simple-model MODEL] \
  [--default] \
  [--project PROJ]

# Lista agentes num âmbito, ou todos os agentes.
pepe agent list [--project PROJ | --all]

# Imprime o system prompt totalmente montado - não só o campo de persona, tudo o que o
# Pepe constrói à volta dele. Ver "A ver exatamente o que o modelo vê" abaixo.
pepe agent prompt NAME [--project PROJ]

# Directed messaging: let FROM message TO.
pepe agent route FROM TO [--remove] [--project PROJ]

# Management authority: let ADMIN administer TARGET (or "*" for all).
pepe agent manage ADMIN TARGET [--remove] [--project PROJ]

# Rename an agent and move its workspace directory.
pepe agent rename OLD NEW

# Delete an agent.
pepe agent remove NAME [--project PROJ]

# Set the default agent for a scope.
pepe agent default NAME [--project PROJ]

Correr um agente

O mesmo agente é alcançável de quatro formas.

De uma só vez pela CLI. Sem sessão, transmite para o stdout.

pepe run assistant "your prompt here"

Consola interativa. Mantém a conversa, por isso o contexto passa de um turno para o outro. Retoma ou separa sessões de consola com --session KEY.

pepe tui assistant

Por HTTP e WebSocket. Arranca o servidor e depois chama a API compatível com OpenAI ou abre um WebSocket de transmissão. O campo model do pedido nomeia o agente.

pepe serve --port 4000
POST /v1/chat/completions
Content-Type: application/json

{
  "model": "assistant",
  "messages": [{ "role": "user", "content": "your prompt here" }]
}

O WebSocket é servido em ws://localhost:4000/socket/websocket, e a verificação de saúde em GET /health.

Através de um canal de mensagens. Liga um agente a uma ligação de Telegram, WhatsApp, Slack, Discord, Microsoft Teams ou Google Chat, ou a um webhook de entrada genérico, e ele responde ali com o mesmo ciclo e as mesmas ferramentas.

Gerir uma persona a partir do Langfuse

Define langfuse_prompt com o nome de um prompt e a persona deste agente passa a vir do Langfuse em vez do próprio system_prompt/SOUL.md: edita o prompt no Langfuse e a alteração chega ao Pepe dentro de poucos minutos, sem redeploy e sem tocar no config.json.

pepe agent add support --langfuse-prompt support-persona

Opt-in por agente - um agente sem langfuse_prompt definido fica completamente inalterado, e um cuja obtenção falhe (inacessível, o nome não resolve) cai diretamente para a persona local. Configuração e credenciais: Langfuse.

A ver exatamente o que o modelo vê

O campo system_prompt é só a semente. O que realmente vai para o modelo como mensagem de sistema também inclui os ficheiros de persona/identidade/boot do agente, se os tiver, um contrato de comportamento curto, a hora atual e um índice dos docs e skills que conhece - nada disto aparece se só leres o campo no disco. Para ver a coisa toda, montada exatamente como uma conversa real a enviaria:

pepe agent prompt NAME

A página de edição do agente no dashboard tem a mesma vista, em Prompt montado