Gatilhos
Um gatilho inicia uma sessão em um horário programado, por meio de um webhook, de um evento de aplicativo ou de um monitor.
Um gatilho inicia uma sessão sem a presença de uma pessoa. Use um gatilho para automatizar tarefas recorrentes ou acionadas por eventos.
Para dar continuidade à tarefa de uma sessão mais tarde — “verifique amanhã se responderam” — use um lembrete. Um lembrete é um gatilho vinculado àquela sessão. Ele fica no banco de dados, não em beeuni.yaml.
Tipos de gatilho
O Beeuni oferece suporte a quatro tipos de gatilho.
- cron — é executado conforme uma programação definida por você.
- webhook — é executado quando um serviço externo envia uma solicitação assinada para a URL de webhook do projeto.
- event — é executado quando algo acontece em um app conectado, como uma nova solicitação de pull ou um novo e-mail. Consulte Gatilhos de eventos de app.
- monitor — executa um comando do seu repositório 24 horas por dia, 7 dias por semana. Cada linha que o comando imprime em stdout dispara o gatilho. Experimental: consulte Monitores.
Você define os gatilhos no manifesto do projeto, beeuni.yaml. Cada gatilho contém um prompt que é exibido como a primeira mensagem da sessão iniciada. O estado de execução — como o horário do último disparo e o status — fica fora do manifesto, no banco de dados. Disparar um gatilho não cria um commit.
Criar, atualizar ou excluir um gatilho pelo dashboard grava diretamente na branch padrão. Isso não passa por uma solicitação de alteração (CR). Editar beeuni.yaml em uma sessão e executar beeuni ship segue o fluxo normal de branches e CRs.
Configurar um gatilho cron
Adicione o gatilho
beeuni triggers add daily-digest --type cron \
--cron "0 0 9 * * 1-5" --timezone America/Los_Angeles \
--prompt "Summarize yesterday's activity and save it as a daily note."cron é uma expressão de 6 campos: segundo, minuto, hora, dia, mês e dia da semana. Um gatilho é disparado no máximo uma vez por minuto: 0 */30 * * * * significa a cada 30 minutos, e */30 * * * * * (a cada 30 segundos) é recusado. Este comando edita apenas o beeuni.yaml local.
Publique
beeuni shipbeeuni ship faz o commit de beeuni.yaml e o envia. A programação entra em vigor quando isso chega à branch padrão do projeto.
Confirme que está funcionando
beeuni triggers lsA lista mostra o slug e o estado de cada gatilho, além do horário do último disparo. Para dispará-lo agora, sem esperar pelo horário programado, execute beeuni triggers fire daily-digest. O comando aguarda o resultado da execução e retorna um código diferente de zero com o texto do erro quando ela falha; --wait <dur> limita o tempo de espera (padrão: 90s).
Configurar um gatilho de webhook
Um gatilho de webhook precisa de um segredo. O Beeuni o usa para verificar a assinatura de cada solicitação recebida.
Adicione o segredo
beeuni secrets set WEBHOOK_SECRET=<a-random-value>Consulte Segredos para saber mais sobre segredos.
Adicione o gatilho
beeuni triggers add new-lead --type webhook \
--secret-env WEBHOOK_SECRET \
--prompt "A new lead arrived: {{ body.name }} ({{ body.email }}). Add it to the CRM."--secret-env indica o segredo que assina as solicitações para este gatilho.
Publique
beeuni shipEnvie uma solicitação
O Beeuni monta a URL do webhook usando o ID do projeto e o slug do gatilho:
POST /v1/webhooks/projects/<project-id>/<slug>Envie uma solicitação POST assinada para esta URL pelo serviço externo. O Beeuni verifica a assinatura usando WEBHOOK_SECRET e inicia uma sessão com o corpo da solicitação disponível no prompt. Consulte Assinatura de webhook abaixo para ver o cabeçalho e o formato exatos.
Por padrão, cada disparo inicia uma sessão nova em uma nova branch. Em vez disso, um gatilho pode reutilizar ou fixar uma sessão, e um gatilho de webhook pode filtrar quais payloads iniciam uma sessão — consulte Estratégia de sessão e Modelagem de payload abaixo.
Gatilhos de eventos de app
Um gatilho de evento executa um agente quando ocorre um evento em um app: uma solicitação de pull é aberta, um e-mail chega, o estado de um problema muda. Você não precisa configurar um webhook, um segredo ou uma assinatura. O Beeuni assina o evento por você, sem que você precise criar uma assinatura manualmente.
Um evento vem de uma fonte de eventos: um adaptador que entrega os eventos de um app. IDs como GITHUB_PULL_REQUEST_CREATED identificam os eventos compatíveis com essa fonte. Use o catálogo de eventos para selecionar um evento para seu conector.
Configurar no app web
- Abra o projeto e acesse Triggers e New trigger.
- Escolha App event.
- Escolha um app. Abaixo dele, escolha um conector e uma de suas contas compartilhadas, ou conecte outra conta. A conta marcada como Default é usada, a menos que você escolha outra.
- Escolha um evento. Abaixo dele, aparece o formulário das configurações do evento, como o repositório.
- Escreva o prompt e salve.
O gatilho entra em vigor assim que o selo mostra Live. Os outros selos são Activating, Needs connection e Error. Eles correspondem aos status pending, needs_connection e error abaixo.
Veja todos os gatilhos de eventos de app
No app web, abra Triggers e escolha App events. A linha de filtros mostra All, Schedules, App events e Webhooks, cada um com uma contagem. A escolha fica no endereço como ?type=event, para que você possa criar um link para ela. As linhas são agrupadas por app. Abaixo delas, Apps with events lista todos os apps que podem iniciar um agente, com primeiro lugar para os apps que o projeto já usa. Escolha um para abrir o formulário de novo gatilho com esse app selecionado.
A janela de um conector tem uma aba Triggers com os eventos de app daquele conector. A aba aparece apenas para apps que têm eventos.
Com a CLI:
beeuni triggers ls --type event # every app event trigger, grouped by app
beeuni triggers ls --connector github-work # the app events on one connector
beeuni triggers ls --type event --json # the same list as JSON
--type também aceita cron, webhook e monitor. --connector e --type podem ser combinados.
Configurar com a CLI
Um agente ou uma pessoa executa estas etapas na ordem. Cada etapa exibe o que a etapa seguinte precisa.
beeuni triggers events --apps
beeuni triggers events --app github
beeuni connectors add github --provider composio --app github --apply
beeuni connectors connect github --owner project
beeuni triggers events --connector github
beeuni triggers events --connector github --event GITHUB_PULL_REQUEST_CREATED
beeuni triggers add pr-review --type event \
--connector github --event GITHUB_PULL_REQUEST_CREATED \
--config repo=hekmat/api \
--prompt "Review {{ event.data.html_url }}" --apply
beeuni triggers info pr-review
triggers events --appslista os apps que podem disparar eventos. Os apps são agrupados por fonte de eventos (source: composio). Cada app lista seus conectores (perfis) e as contas compartilhadas deles. A colunaSTATEmostraconnectedouneeds account; os apps sem conector aparecem emNo connector yet.connectors addadiciona o conector quando o app não tem nenhum. Ignore esta etapa quandoCONNECTORestiver definido.connectors connect <slug> --owner projectexibe um link. Uma pessoa o abre para conectar a conta compartilhada. Uma conta privada de um membro não é aceita. Execute o comando novamente para adicionar uma segunda conta compartilhada e, em seguida, dê um nome a ela comconnectors rename <id> <label>.triggers events --connector <slug>lista os eventos. Adicione--event <TYPE>para ver as configurações de um evento e suas variáveis{{ event.data.* }}. Leia a descrição de cada configuração: alguns eventos aceitam o nome completo em uma única configuração, comorepo: hekmat/api, e recusam o mesmo valor dividido entreownererepo.triggers add --applycria o gatilho imediatamente e exibe seu status e a próxima etapa. Se uma configuração estiver ausente ou for inválida, o comando retorna o código 2 e lista todos os problemas. Sem--apply, a CLI grava o bloco nobeeuni.yamllocal; executebeeuni shippara aplicá-lo.triggers info <slug>mostra o status. Repita até que ele mostrelive.
--source <adapter> define a fonte de eventos e é opcional: sem ela, o gatilho usa o provedor do conector. O conector precisa pertencer a essa fonte. Uma fonte composio em um conector de outro provedor mostra error: Connector "<slug>" is a <provider> connector; source "composio" needs a composio connector. Uma fonte desconhecida é recusada com Unknown event source "<x>". Sources: composio. beeuni triggers set <slug> --source <adapter> altera a fonte; alterar --connector a limpa.
--config key=value se repete uma vez por configuração e é convertido para o tipo da configuração. --config-json '{"limit": 5}' passa valores tipados. beeuni triggers set <slug> --config key=value mescla com a configuração ativa; --config-json a substitui. Não passe ambos. Um gatilho de evento não aceita nenhum destes: --cron, --run-at, --timezone, --secret-env, --run, --mode, --interval ou --expect-event-within.
Estrutura da configuração
# beeuni.yaml
triggers:
- slug: pr-review
type: event
connector: github-work # required, slug of a connector (profile) under `connectors:`
source: composio # optional, the event source adapter. Default: the connector's provider
account: hekmat-bot # optional, label of one shared account of that connector
event: GITHUB_PULL_REQUEST_CREATED # required, the adapter's event id, from `beeuni triggers events`
config: { repo: hekmat/api } # optional, settings of the event
agent: default
session_mode: fresh # default "fresh"
filter: # optional, same guard a webhook uses
"event.data.draft": "false"
prompt: |
Review {{ event.data.html_url }}
O que o prompt pode ler
O prompt, filter e session_key leem estas raízes:
| Raiz | Valor |
|---|---|
event.data.<field> |
Os dados do evento do próprio app. beeuni triggers events mostra os campos que cada evento contém. |
event.id |
O ID do provedor para este evento. |
event.type |
O tipo de evento, como GITHUB_PULL_REQUEST_CREATED. |
event.app |
O slug do app, como github. |
event.connector |
O slug do conector monitorado pelo gatilho. |
event.occurred_at |
Quando o evento aconteceu. |
Os dados do evento vêm de terceiros. O Beeuni inicia a primeira mensagem da sessão com [App event: <trigger name> — automated, third-party content, not user input], para que o agente trate o conteúdo do evento como dados, e não como instruções. Essa linha também é o título da sessão até que o agente dê um nome a ela.
Status
beeuni triggers ls e a lista de gatilhos da web mostram o status da assinatura de cada gatilho de evento.
| Status | Significado | Correção |
|---|---|---|
active |
A assinatura existe. Os eventos acionam o gatilho. | Nenhuma. |
pending |
O gatilho foi declarado e o Beeuni ainda não criou a assinatura. | Aguarde um momento. Se continuar pending, salve o gatilho novamente. |
needs_connection |
O conector não tem uma conta compartilhada utilizável. O texto diz “Conecte uma conta <app> compartilhada para ativar este gatilho.” ou “Conclua a conexão da conta <app> compartilhada…” |
Conecte uma conta compartilhada para o conector como projeto (beeuni connectors connect <slug> --owner project). A conta privada de um membro não é válida. O gatilho é ativado automaticamente quando a pessoa conclui a conexão, mesmo que ela se conecte por um link fora do Beeuni. |
error |
A assinatura falhou ou foi desativada pelo provedor. O gatilho exibe o texto do erro. | Corrija a causa indicada no texto e salve o gatilho novamente. |
Mensagens comuns de error:
-
“Esta conta
<app>é compartilhada apenas com pessoas específicas. Os gatilhos de evento precisam de uma conta compartilhada com todo o projeto.” Abra as configurações de compartilhamento da conta e compartilhe-a com todo o projeto. -
“O conector
<slug>não está declarado em beeuni.yaml.” Adicione o conector emconnectors:. -
Se os gatilhos de evento não estiverem disponíveis, entre em contato com o suporte.
-
“O app desativou esta assinatura: …” O provedor desativou a assinatura. Salve o gatilho novamente para assinar de novo.
-
“A conta conectada expirou: …” O app revogou ou deixou a conta expirar. Reconecte o app para reativar o gatilho.
Regras
- Conector e conta. Um app é o serviço, como o GitHub. Um conector é um perfil em
beeuni.yaml; vários conectores podem compartilhar um app. Uma conta é um login conectado dentro de um conector. Um gatilho indica um conector. Ele usa a conta compartilhada padrão desse conector, a menos que definaaccount: <label>. Definaaccountapenas quando um conector tiver várias contas compartilhadas. Na CLI,--account <label>define esse valor e--default-account(emtriggers set) o remove. Um rótulo que não corresponda a nenhuma conta compartilhada resulta emneeds_connection, com o texto “Conecte uma conta<app>compartilhada com o rótulo “<label>” em<connector>.“ - Uma conta de origem. Apenas uma conta compartilhada com o projeto e acessível a todo o projeto pode alimentar um gatilho. Um gatilho é executado sem ninguém presente, e os dados do evento são inseridos em um prompt de sessão. Uma conta compartilhada apenas com pessoas específicas ou uma conta privada nunca pode alimentá-lo.
- Cada evento é acionado uma vez. Um gatilho é acionado uma vez por evento do provedor. A reentrega de um evento não inicia uma segunda sessão. Dois gatilhos para o mesmo evento são acionados uma vez cada.
- Pausar interrompe. Um gatilho pausado ou um projeto pausado ignora os eventos. Os eventos ignorados não ficam na fila.
- As edições criam uma nova assinatura. Alterar
connector,source,account,eventouconfigsubstitui a assinatura. Excluir o gatilho o remove.
Monitores
Experimental. Os monitores só são executados quando a flag de recurso monitors está ativada. Por padrão, a flag fica desativada. Enquanto estiver desativada, a plataforma não provisiona uma caixa de monitor nem dispara eventos de monitor.
Um monitor observa algo que não envia webhooks nem se encaixa em um agendamento: um log em tempo real, a profundidade de uma fila, uma página que muda, um preço. O Beeuni executa seu comando 24 horas por dia, 7 dias por semana, na caixa de monitor do projeto — uma microVM persistente por projeto, com o mesmo limite de isolamento e os mesmos segredos do projeto que um sandbox de sessão recebe. Código determinístico monitora; o agente é ativado apenas quando o comando emite uma linha.
Quatro regras definem o contrato:
- Linhas de stdout são eventos. Nada mais é. Stderr contém diagnósticos: visíveis nos logs do monitor, nunca disparam eventos.
- Cada linha dispara o gatilho exatamente uma vez, pelo caminho já usado por um webhook:
filter→ modelo de prompt →session_mode. - Um monitor não pode falhar silenciosamente. A saída do processo, o esgotamento do limite de reinicializações e o silêncio por mais de
expect_event_withindisparam, cada um, um evento de ciclo de vida escrito pela plataforma no mesmo fluxo. session_modeusareusepor padrão em um monitor, nãofresh. Um monitor é projetado para disparar repetidamente, entãofreshcriaria uma sessão por evento.
Adicionar o monitor
beeuni triggers add checkout-errors --type monitor \
--run "./monitors/checkout-errors.ts" \
--mode poll --interval 60s --expect-event-within 24h \
--prompt "Checkout monitor emitted: {{ line }}"--mode poll executa novamente o comando a cada --interval e espera que ele seja encerrado. --mode stream executa o comando uma vez e o mantém ativo; um fluxo não aceita --interval. Ambos os formatos produzem linhas, e nenhum componente posterior consegue distingui-los. cron, run_at, timezone e secret_env não são aceitos em um monitor.
Publique
beeuni shipA plataforma inicia a caixa do monitor quando isso chega à ramificação padrão.
Confirme que está em execução
beeuni triggers ls
beeuni triggers info checkout-errorsls mostra o modo e o intervalo de um monitor, enquanto um cron mostra a programação. info mostra run, mode, interval e expect_event_within.
Limites dos monitores
Todos os limites abaixo são impostos pela plataforma.
| Limite | Valor |
|---|---|
| Monitores por projeto | 10 ativados |
| Intervalo de consulta | pelo menos 30s |
expect_event_within |
pelo menos 5m |
| Taxa de eventos por monitor | 60/hora de forma contínua, rajada de 30. O excedente suprime o monitor por 10 minutos; 3 supressões em 24 horas o desativam. |
| Tamanho da linha | 8 KiB, truncada com um marcador truncated: true |
| Limite de reinicializações | 5 reinicializações / 10 minutos; depois, um evento de ciclo de vida restart_budget_exhausted e uma espera de 15 minutos |
| Retenção de eventos | 30 dias |
| Orçamento mensal da caixa | US$ 75 por padrão. Ao excedê-lo, a caixa é interrompida e um evento de ciclo de vida budget_exceeded é disparado. |
A caixa do monitor precisa de um provedor compatível com um sandbox persistente. Se o provedor do projeto não puder manter um, a flag monitors indicará que o recurso está indisponível.
Estrutura da configuração
# beeuni.yaml
triggers:
- slug: daily-digest # required, lowercase + dashes, unique per project
name: Daily digest # optional, defaults to slug
type: cron # "cron" | "webhook" | "event" | "monitor", required
agent: beeuni # optional, defaults to "default"
model: anthropic/claude-sonnet-4-5 # optional, resolves at fire time if unset
enabled: true # optional, default true
cron: "0 0 9 * * 1-5" # 6-field expression, mutually exclusive with run_at
timezone: America/Los_Angeles # IANA name, default UTC
session_mode: reuse # "fresh" | "reuse" | "pinned" | "keyed", default "fresh"
filter: # optional, webhook payload guard
"body.data.direction": "inbound"
prompt: "Summarize {{ body.text }}" # required, template string
Um monitor substitui os campos de agendamento pelo comando e pelo formato:
# beeuni.yaml
triggers:
- slug: checkout-errors
type: monitor
run: ./monitors/checkout-errors.ts # required, repo-relative command
mode: poll # "poll" | "stream", required
interval: 60s # required on poll, invalid on stream
expect_event_within: 24h # optional silence watchdog
agent: oncall
session_mode: reuse # the monitor default
filter: # optional, same guard a webhook uses
"line.severity": "error"
prompt: "Checkout monitor emitted: {{ line }}"
Um gatilho de evento substitui os campos de agendamento pelo app e pelo evento monitorado. Consulte Gatilhos de evento de app.
beeuni.toml legado usa os mesmos campos em um contêiner diferente; consulte TOML legado.
Campos
| Campo | Obrigatório | Padrão | Observações |
|---|---|---|---|
slug |
sim | — | [a-z0-9][a-z0-9_-]{0,127}, exclusivo por projeto. |
type |
sim | — | cron, webhook ou monitor. |
prompt |
sim | — | String de modelo. É exibida como a primeira mensagem da sessão. |
name |
não | slug |
Rótulo legível. |
agent |
não | default_agent |
Deve corresponder a uma chave em agents:. Omita para usar default_agent; não escreva o literal default. |
model |
não | resolvido no momento do disparo | Formato de transmissão provider/model, por exemplo anthropic/claude-sonnet-4-5. |
enabled |
não | true |
Quando false, o agendador e o receptor de webhook ignoram a entrada. |
session_mode |
não | fresh ou reuse em um monitor |
Consulte Estratégia de sessão. |
session_id |
obrigatório para pinned |
— | Sessão exata a ser solicitada novamente. |
session_key |
obrigatório para keyed |
— | String de modelo. Defini-la por si só implica session_mode: keyed. |
filter |
não | — | Caminho pontuado → string esperada. Uma entrega de webhook que não corresponda retorna 200 e não dispara nenhuma sessão. |
cron |
um de cron/run_at, em type: cron |
— | Expressão de 6 campos: segundo minuto hora dia mês dia da semana. Dispara no máximo uma vez a cada 60 segundos; uma expressão mais rápida falha em beeuni validate e na API. |
run_at |
um de cron/run_at, em type: cron |
— | Carimbo de data/hora ISO-8601. Dispara uma vez e depois fica inativo. |
timezone |
não, somente cron | UTC |
Nome IANA. |
secret_env |
obrigatório, somente webhook | — | Nome de um segredo do projeto que contém a chave de assinatura. O segredo deve usar a entrega broker com o consumidor connector. |
run |
obrigatório, somente monitor | — | Comando relativo ao repositório cujas linhas de stdout são os eventos. Uma linha, no máximo 1024 caracteres. |
mode |
obrigatório, somente monitor | — | poll executa run novamente a cada interval; stream executa uma vez e o mantém ativo. |
interval |
obrigatório para mode: poll |
— | Duração literal (30s, 5m, 24h, 7d), mínimo de 30s. Inválido em mode: stream. |
expect_event_within |
não, somente monitor | — | Duração literal, mínimo de 5m. Um período de silêncio superior a esse valor dispara um evento de ciclo de vida. |
Um gatilho cron precisa de cron ou run_at, nunca de ambos. Um gatilho de webhook sem secret_env é rejeitado — não há webhook sem autenticação. Um monitor precisa de run e mode, e rejeita cron, run_at, timezone e secret_env sem exceção — um manifesto que declara um agendamento que o executor do monitor nunca lê é uma mentira.
Configure o segredo de assinatura antes de criar ou atualizar um gatilho de webhook:
beeuni secrets set WEBHOOK_SECRET=-
beeuni secrets delivery WEBHOOK_SECRET broker --consumer connector
Passe o valor para o primeiro comando pela entrada padrão. Se o segredo usava anteriormente a entrega sandbox, alterne-o após mudar o tipo de entrega, pois uma sandbox existente pode manter o valor anterior.
Estratégia de sessão
session_mode controla qual sessão é solicitada novamente quando ocorre um disparo. Beeuni tenta os modos abaixo na ordem indicada e, se cada etapa falhar, passa para a próxima.
pinned— solicita novamente asession_idexata. Se essa sessão não existir mais ou tiver falhado, passa para a próxima opção.keyed— renderizasession_keycom base no payload e procura a sessão mais recente, sem falhas, identificada anteriormente com essa chave exata. Se a chave renderizada ficar vazia ou nenhuma sessão corresponder, passa para uma nova sessão. Nunca passa para a sessão de outra chave.reuse— solicita novamente a sessão mais recente, sem falhas, criada anteriormente por esse gatilho. Um gatilho fixado também recorre a essa opção antes de continuar.fresh— cria uma nova sandbox e ramificação. Esse é o padrão e a última alternativa para todos os modos. A nova sessão passa a ser a sessão do gatilho para futuros disparos dereuseekeyed.
Uma sessão reuse ou keyed cujo histórico não caiba mais no modelo, mesmo após a compactação automática, é aposentada. O próximo disparo inicia uma sessão nova. Qualquer outra falha mantém a sessão para o próximo disparo.
Um gatilho cron frequente que não deve reenviar um histórico cada vez maior pode renovar a sessão na virada do calendário: session_key: "merge-{{ cron.scheduled_date }}" mantém uma sessão serializada por dia UTC, e {{ cron.scheduled_hour }} mantém uma por hora UTC.
Execuções com falha
Quando uma execução iniciada por um gatilho termina com erro, Beeuni registra isso no gatilho:
last_statuspassa a serfailedelast_errorcontém o motivo, por exemploOut of credits: Payment Required: Insufficient credits.- A página Agendamento marca o gatilho como “A última execução não foi concluída” e exibe o motivo no painel.
- O proprietário da conta recebe uma notificação push no celular quando a primeira execução falha. Uma falha posterior atualiza o motivo sem enviar outra notificação push.
- O gatilho permanece
failedenquanto continua disparando. Um novo disparo não comprova que a execução foi bem-sucedida.
A próxima execução concluída elimina a falha. Uma execução interrompida por você, um subagente e uma chamada de modelo repetida não contam como resultados de execução. Uma falha antes do início da execução, por exemplo, quando não é possível criar uma sessão, é eliminada no próximo disparo bem-sucedido.
Acesso à sessão
Por padrão, as sessões criadas por um gatilho usam a política privada. A conta de serviço do agente do gatilho é a proprietária — a identidade de um agente é um principal service_account, portanto pode possuir uma sessão e ter atribuições como qualquer outro principal. Um gerente do projeto sempre pode abri-las. O proprietário da conta e um administrador da conta têm acesso equivalente ao de gerente em todos os projetos, portanto o mesmo se aplica a eles. A pessoa que configurou ou acionou manualmente o gatilho não obtém acesso por essa ação, a menos que tenha uma dessas funções.
As configurações do gatilho oferecem três políticas:
- Agente do gatilho e gerentes do projeto — nenhum membro comum do projeto pode abrir a sessão.
- Colegas de equipe selecionados — o agente do gatilho, os gerentes do projeto e os membros do projeto ou grupos de contas selecionados.
- Projeto inteiro — todos os membros do projeto.
Essa política é uma configuração de visibilidade por recurso, aplicada sobre o modelo de funções, não uma função. Ela determina quem pode abrir as sessões de um gatilho. Não concede nenhuma permissão negada pela decisão da função. Consulte Contas e acesso.
A política de acesso é um estado de execução local à conta. Ela não faz parte do manifesto beeuni.yaml portátil porque os IDs dos principais pertencem a uma única conta. Use o painel para configurá-la.
Atualizar somente essa política não cria nenhum commit do Git. Salvar uma política também atualiza as sessões anteriores criadas por esse gatilho.
Uma sessão fixada mantém suas próprias configurações de compartilhamento porque não foi criada pelo gatilho. Se uma sessão fixada estiver indisponível e o gatilho criar uma sessão alternativa, a política do gatilho se aplicará a essa nova sessão.
Modelagem de payload
prompt e session_key são renderizados com o mesmo mecanismo: {{ token.dotted.path }}. Um valor ausente é renderizado como uma string vazia — sem erro nem {{ }} restante. Objetos e arrays são renderizados como JSON. session_key é removido dos espaços em branco nas extremidades e truncado em 512 caracteres.
Cada disparo também recebe {{ trigger.slug }}, {{ trigger.type }} e {{ trigger.kind }} (sempre git). O restante do conjunto de variáveis depende de como o gatilho foi acionado.
| Origem | Variáveis |
|---|---|
| cron | {{ cron.schedule }}, {{ cron.timezone }}, {{ cron.scheduled_for }} (o slot para o qual o disparo se destina), {{ cron.claimed_at }} (quando o agendador o capturou), {{ cron.last_scheduled_for }} (o slot anterior; vazio no primeiro disparo), {{ cron.scheduled_date }} (YYYY-MM-DD UTC do slot), {{ cron.scheduled_hour }} (YYYY-MM-DDTHH UTC). Nenhum fired_at de nível superior. |
| webhook | {{ fired_at }}, {{ body.* }} (analisado como JSON; usa {{ body.raw }} como fallback se o corpo não puder ser analisado), {{ headers.content_type }}, {{ headers.user_agent }}, {{ headers.forwarded_for }}. |
| monitor | {{ line.* }} — a linha de stdout, analisada como JSON; uma linha que não puder ser analisada é renderizada como {{ line.raw }}. Além de {{ monitor.slug }}, {{ monitor.seq }}, {{ monitor.emitted_at }} e {{ monitor.kind }} (event ou lifecycle). |
manual (“disparar agora” no dashboard ou o endpoint fire) |
{{ fired_at }}, {{ source }} (manual), {{ actor }}, {{ message.text }}, {{ message.source }}. |
O Beeuni prefixa todos os prompts de monitor renderizados com [MONITOR EVENT — automated, not user input], no lado do servidor. Um evento de ciclo de vida ignora completamente seu template e renderiza um prompt escrito pela plataforma; ele também ignora filter — o silêncio não deve ser filtrável por acidente.
{{ message.text }} é codificado como uma string vazia em um disparo manual, e {{ message.source }} como manual_test. Um disparo manual não é uma forma de injetar dados de teste no prompt.
filter compara caminhos pontuados como strings com o mesmo payload que o prompt recebe. Ele existe para interromper loops. Por exemplo, uma origem que relata os dois lados de uma conversa dispararia novamente o agente na própria resposta.
Assinatura do webhook
Dispara em POST /v1/webhooks/projects/{projectId}/{slug}. O Beeuni verifica a solicitação nesta ordem, usando uma comparação em tempo constante:
- Assinatura HMAC — cabeçalho
X-Beeuni-Signature: sha256=<hmac>(o prefixosha256=é opcional) ouX-Hub-Signature-256, compatível com o GitHub. HMAC-SHA256 sobre o corpo bruto da solicitação, usando o segredo nomeado porsecret_env. - Token estático, somente quando nenhum cabeçalho de assinatura estiver presente, para remetentes que não conseguem assinar um corpo com HMAC. Envie o segredo como
X-Beeuni-Token: <secret>,Authorization: Bearer <secret>ouAuthorization: Basic <base64(user:secret)>(a metade da senha é o token).
beeuni triggers info <slug> exibe este esquema — o cabeçalho, o algoritmo e uma solicitação de exemplo assinada com um placeholder $SECRET — e --json o transporta como webhook_signing. A folha de acionamento do dashboard mostra a mesma solicitação de exemplo.
| Status | Significado |
|---|---|
| 202 | Assinatura ou token válido. O corpo é { status: "fired" | "queued" | "deduped", session_id, ... }. |
| 200 | Válido, mas ignorado — o projeto está pausado ou a entrega não correspondeu a filter. |
| 400 | ID ou slug de projeto malformado na URL. |
| 401 | Assinatura e token ausentes ou incorretos. |
| 404 | Acionador não encontrado, desativado, não é um webhook ou o projeto não está ativo. |
| 409 | O segredo de assinatura está ausente, inativo, indisponível ou não autoriza o consumidor connector. A resposta inclui um código webhook_secret_* e instruções de correção. |
| 500 | A autenticação passou, mas a sessão não conseguiu disparar. |
Endpoints
| Método + caminho | Necessário | Observações |
|---|---|---|
GET /v1/projects/{projectId}/triggers |
project.trigger.read |
Lista acionadores, estado de execução (last_fired_at, last_status, last_error, last_attempt_at) e erros de análise do manifesto. Uma entrada inválida aparece em errors[]; ela não interrompe os outros acionadores. |
POST /v1/projects/{projectId}/triggers |
project.trigger.create |
Cria um acionador. Faz commit diretamente no manifesto. |
PATCH /v1/projects/{projectId}/triggers/{slug} |
project.trigger.update |
Atualização parcial, mesclada à entrada atual. |
DELETE /v1/projects/{projectId}/triggers/{slug} |
project.trigger.delete |
Também limpa o estado de execução do acionador. |
PATCH /v1/projects/{projectId}/triggers/activation |
project.trigger.update |
Corpo { paused: boolean }. Consulte Pausar e retomar. |
POST /v1/projects/{projectId}/triggers/{slug}/fire |
project.trigger.fire |
Disparo manual. A função integrada de projeto member detém project.trigger.fire, portanto um membro comum pode disparar um acionador. |
POST /v1/webhooks/projects/{projectId}/{slug} |
assinatura ou token | URL pública, protegida pelo segredo do webhook. |
Pausar e retomar
Uma chave no nível do projeto interrompe todos os acionadores do projeto de uma só vez, independentemente do campo enabled de cada acionador. Enquanto pausado, o agendador ignora o projeto e os webhooks recebidos retornam 200 com { status: "skipped" } — nenhuma sessão é disparada. Um disparo manual continua funcionando. Use isso quando o mesmo repositório for executado em dois planos de controle (por exemplo, desenvolvimento e produção), para que o cron não dispare duas vezes. CLI: beeuni triggers pause e beeuni triggers resume. Consulte CLI para o grupo completo de comandos beeuni triggers.
Limites e confiabilidade
- O agendador consulta aproximadamente a cada segundo (1.000 ms por padrão; configurável via
BEEUNI_TRIGGER_SCHEDULER_INTERVAL_MS). Uma execução do cron não começa exatamente no slot: cada acionador recebe um deslocamento fixo de até um quarto do período, no máximo 30 minutos, para que muitos acionadores no mesmo minuto não comecem ao mesmo tempo. Os detalhes do acionador eGET /triggers(next_fire_at) mostram o horário em que a próxima execução começa. - Um disparo que falha define o último status do acionador como failed, com o erro. Isso vale para todas as origens: cron, manual, webhook, evento de aplicativo e monitor. O próximo disparo bem-sucedido limpa um disparo com falha. Uma execução com falha é limpa conforme descrito em Execuções com falha.
- Cada projeto permite, por padrão, 3 sessões acionadas em provisionamento simultaneamente. Um disparo que ultrapasse esse limite retorna
queued(202) em vez de falhar e é executado quando uma delas termina o provisionamento. Não há limite para quantas sessões podem ser executadas simultaneamente. - Um disparo manual ou de webhook tem um tempo limite de 45 segundos. O carregamento do manifesto tem um tempo limite de 30 segundos.
- Um disparo de cron é associado ao slot de agendamento devido, portanto um disparo que atingiu o tempo limite, mas foi efetivamente concluído, não é duplicado na nova tentativa.
- Uma entrega de webhook é executada uma vez por evento. O Beeuni lê o ID do evento de
X-Beeuni-Delivery-Id,X-GitHub-Delivery,X-Gitlab-Event-UUID,Linear-Delivery,webhook-idousvix-id, nessa ordem; uma nova tentativa com o mesmo ID responde202 { status: "deduped" }e não executa nada.X-Request-Idnão é um ID de evento. Sem um ID de evento, um corpo e uma assinatura idênticos dentro de 10 minutos contam como o mesmo evento; depois disso, ele é executado novamente, portanto um job que publica o mesmo corpo estático em cada implantação é executado em cada implantação. EnvieX-Beeuni-Delivery-Idcom um novo valor por evento (a solicitação de exemplo usa$(uuidgen)). - Uma entrega cuja tentativa anterior falhou definitivamente (por exemplo, a conta ficou sem créditos) ou cuja sessão foi excluída é executada novamente quando reenviada com o mesmo ID. Uma duplicata não altera
last_fired_at.