Trigger
Un trigger avvia una sessione in base a una pianificazione, tramite un webhook, in seguito a un evento di un’app o da un monitor.
Un trigger avvia una sessione senza la presenza di una persona. Usa un trigger per automatizzare attività ricorrenti o guidate da eventi.
Per occuparsi in seguito dell’attività di una sessione — «controlla domani se hanno risposto» — usa invece un promemoria. Un promemoria è un trigger limitato a quella sessione. Risiede nel database, non in beeuni.yaml.
Tipi di trigger
Beeuni supporta quattro tipi di trigger.
- cron — viene eseguito secondo una pianificazione configurata.
- webhook — viene eseguito quando un servizio esterno invia una richiesta firmata all’URL webhook del progetto.
- event — viene eseguito quando accade qualcosa in un’app collegata, ad esempio l’apertura di una nuova pull request o la ricezione di una nuova email. Consulta Trigger degli eventi dell’app.
- monitor — esegue un comando dal tuo repository 24 ore su 24, 7 giorni su 7. Ogni riga stampata dal comando su stdout attiva il trigger. Sperimentale: consulta Monitor.
Definisci i trigger nel manifest del progetto, beeuni.yaml. Ogni trigger contiene un prompt che viene visualizzato come primo messaggio della sessione avviata. Lo stato di runtime — ad esempio l’ora dell’ultima attivazione e lo stato — risiede al di fuori del manifest, nel database. L’attivazione di un trigger non crea un commit.
La creazione, l’aggiornamento o l’eliminazione di un trigger tramite il dashboard scrive direttamente nel branch predefinito. Non passa da una richiesta di modifica (CR). La modifica di beeuni.yaml all’interno di una sessione e l’esecuzione di beeuni ship seguono invece il normale flusso di branch e CR.
Configurare un trigger cron
Aggiungi il trigger
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 è un’espressione a 6 campi: secondo, minuto, ora, giorno, mese, giorno della settimana. Un trigger viene attivato al massimo una volta al minuto: 0 */30 * * * * equivale a ogni 30 minuti, mentre */30 * * * * * (ogni 30 secondi) viene rifiutato. Questo comando modifica solo il tuo beeuni.yaml locale.
Distribuiscilo
beeuni shipbeeuni ship esegue il commit di beeuni.yaml e lo invia al repository remoto. La pianificazione diventa attiva quando questo viene applicato al branch predefinito del progetto.
Verifica che venga eseguito
beeuni triggers lsL’elenco mostra lo slug, lo stato e l’ultima attivazione di ogni trigger. Per attivarlo subito invece di attendere la pianificazione, esegui beeuni triggers fire daily-digest. Il comando attende l’esito dell’esecuzione ed esce con un codice diverso da zero e il testo dell’errore quando l’esecuzione fallisce; --wait <dur> limita il tempo di attesa (valore predefinito 90s).
Configurare un trigger webhook
Un trigger webhook richiede un segreto. Beeuni lo usa per verificare la firma di ogni richiesta in ingresso.
Aggiungi il segreto
beeuni secrets set WEBHOOK_SECRET=<a-random-value>Consulta Segreti per ulteriori informazioni sui segreti.
Aggiungi il trigger
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 il segreto che firma le richieste per questo trigger.
Distribuiscilo
beeuni shipInviagli una richiesta
Beeuni crea l’URL webhook usando l’ID del progetto e lo slug del trigger:
POST /v1/webhooks/projects/<project-id>/<slug>Invia a questo URL una richiesta POST firmata dal servizio esterno. Beeuni verifica la firma rispetto a WEBHOOK_SECRET, quindi avvia una sessione con il corpo della richiesta disponibile nel prompt. Per il nome e il formato esatti dell’intestazione, consulta Firma webhook più avanti.
Per impostazione predefinita, ogni attivazione avvia una nuova sessione su un nuovo branch. Un trigger può invece riutilizzare o bloccare una sessione, mentre un trigger webhook può filtrare i payload che ne avviano una — consulta Strategia della sessione e Modelli dei payload più avanti.
Trigger degli eventi dell’app
Un trigger di evento esegue un agente quando si verifica un evento dell’app: viene aperta una pull request, arriva un’email o un issue cambia stato. Non devi configurare un webhook, un segreto o una firma. Beeuni si iscrive all’evento per te e non firma nulla manualmente.
Un evento proviene da una sorgente di eventi: un adapter che distribuisce gli eventi di un’app. Gli ID come GITHUB_PULL_REQUEST_CREATED identificano gli eventi supportati da quella sorgente. Usa il catalogo degli eventi per scegliere un evento per il tuo connettore.
Configurazione nell’app web
- Apri il progetto, quindi Triggers e New trigger.
- Scegli App event.
- Seleziona un’app. Al suo interno, seleziona un connettore e uno dei suoi account condivisi, oppure collega un altro account. L’account contrassegnato come Default viene usato se non ne selezioni un altro.
- Seleziona un evento. Sotto di esso comparirà il modulo per le impostazioni dell’evento, ad esempio il repository.
- Scrivi il prompt e salva.
Il trigger è attivo non appena il relativo badge mostra Live. Gli altri badge sono Activating, Needs connection e Error. Corrispondono agli stati pending, needs_connection e error descritti di seguito.
Visualizzare tutti i trigger degli eventi dell’app
Nell’app web, apri Triggers e scegli App events. La riga dei filtri mostra All, Schedules, App events e Webhooks, ciascuno con un conteggio. La scelta viene conservata nell’indirizzo come ?type=event, così puoi collegarti direttamente a essa. Le righe sono raggruppate per app. Sotto di esse, Apps with events elenca tutte le app che possono avviare un agente, mettendo per prime quelle già utilizzate dal progetto. Selezionane una per aprire il modulo per un nuovo trigger relativo a quell’app.
La finestra di un connettore contiene una scheda Triggers con gli eventi dell’app relativi a quel connettore. La scheda compare solo per un’app che dispone di eventi.
Con la 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 accetta anche cron, webhook e monitor. --connector e --type possono essere combinati.
Configurazione con la CLI
Un agente o una persona esegue questi passaggi nell’ordine indicato. Ogni passaggio stampa ciò che serve per quello successivo.
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 --appselenca le app che possono attivare eventi. Le app sono raggruppate sotto la relativa sorgente di eventi (source: composio). Ogni app elenca i propri connettori (profili) e i relativi account condivisi. La colonnaSTATEmostraconnectedoneeds account; le app senza connettore compaiono sottoNo connector yet.connectors addaggiunge il connettore quando l’app non ne ha uno. Saltalo quando è impostatoCONNECTOR.connectors connect <slug> --owner projectstampa un link. Una persona lo apre per collegare l’account condiviso. L’account privato di un membro non è valido. Eseguilo di nuovo per aggiungere un secondo account condiviso, quindi assegnagli un’etichetta conconnectors rename <id> <label>.triggers events --connector <slug>elenca gli eventi. Aggiungi--event <TYPE>per le impostazioni di un evento e le relative variabili{{ event.data.* }}. Leggi la descrizione di ogni impostazione: alcuni eventi richiedono un nome completo in una sola impostazione, comerepo: hekmat/api, e rifiutano lo stesso valore suddiviso traownererepo.triggers add --applycrea subito il trigger e stampa il relativo stato e il passaggio successivo. Un’impostazione mancante o non valida termina con il codice 2 ed elenca tutti i problemi. Senza--apply, la CLI scrive il blocco nelbeeuni.yamllocale; eseguibeeuni shipper applicarlo.triggers info <slug>mostra lo stato. Ripeti finché non leggelive.
--source <adapter> imposta la sorgente degli eventi ed è facoltativo: senza di esso, il trigger usa il provider del connettore. Il connettore deve appartenere a quella sorgente. Una sorgente composio su un connettore di un altro provider restituisce error: Connector "<slug>" is a <provider> connector; source "composio" needs a composio connector. Una sorgente sconosciuta viene rifiutata con Unknown event source "<x>". Sources: composio. beeuni triggers set <slug> --source <adapter> la modifica; la modifica di --connector la cancella.
--config key=value si ripete una volta per ogni impostazione e viene convertito nel tipo dell’impostazione. --config-json '{"limit": 5}' passa valori tipizzati. beeuni triggers set <slug> --config key=value esegue il merge nella configurazione attiva; --config-json la sostituisce. Non passarli entrambi. Un trigger di evento non accetta nessuno tra --cron, --run-at, --timezone, --secret-env, --run, --mode, --interval o --expect-event-within.
Struttura della configurazione
# 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 }}
Cosa può leggere il prompt
Il prompt, filter e session_key leggono queste radici:
| Radice | Valore |
|---|---|
event.data.<field> |
I dati dell’evento dell’app. beeuni triggers events mostra i campi trasportati da ogni evento. |
event.id |
L’ID del provider per questo evento. |
event.type |
Il tipo di evento, ad esempio GITHUB_PULL_REQUEST_CREATED. |
event.app |
Lo slug dell’app, ad esempio github. |
event.connector |
Lo slug del connettore monitorato dal trigger. |
event.occurred_at |
Quando si è verificato l’evento. |
I dati dell’evento provengono da terze parti. Beeuni inizia il primo messaggio della sessione con [App event: <trigger name> — automated, third-party content, not user input], così l’agente tratta il contenuto dell’evento come dati e non come istruzioni. Questa riga è anche il titolo della sessione finché l’agente non le assegna un nome.
Stato
beeuni triggers ls e l’elenco dei trigger web mostrano lo stato della sottoscrizione di ogni trigger di evento.
| Stato | Significato | Soluzione |
|---|---|---|
active |
La sottoscrizione esiste. Gli eventi attivano il trigger. | Nesbeeuni. |
pending |
Il trigger è dichiarato e Beeuni non ha ancora creato la sottoscrizione. | Attendi qualche istante. Se rimane pending, salva nuovamente il trigger. |
needs_connection |
Il connettore non dispone di un account condiviso utilizzabile. Il testo visualizzato è “Connect a shared <app> account to activate this trigger.” oppure “Finish connecting the shared <app> account…” |
Connetti un account condiviso per il connettore come progetto (beeuni connectors connect <slug> --owner project). L’account privato di un membro non è sufficiente. Il trigger diventa operativo automaticamente quando la persona termina la connessione, anche se si connette da un link esterno a Beeuni. |
error |
La sottoscrizione non è riuscita oppure il provider l’ha disabilitata. Il trigger mostra il testo dell’errore. | Risolvi la causa indicata dal testo, quindi salva nuovamente il trigger. |
Testi comuni di error:
-
“This
<app>account is shared with specific people only. Event triggers need an account shared with the whole project.” Apri la condivisione dell’account e condividilo con l’intero progetto. -
“Connector
<slug>is not declared in beeuni.yaml.” Aggiungi il connettore sottoconnectors:. -
Se i trigger di evento non sono disponibili, contatta il supporto.
-
“The app disabled this subscription: …” Il provider ha disattivato la sottoscrizione. Salva nuovamente il trigger per sottoscriverlo di nuovo.
-
“The connected account expired: …” L’app ha revocato o fatto scadere l’account. Riconnetti l’app per riattivare il trigger.
Regole
- Connettore e account. Un’app è il servizio, ad esempio GitHub. Un connettore è un profilo in
beeuni.yaml; diversi connettori possono condividere una stessa app. Un account è un singolo accesso connesso sotto un connettore. Un trigger indica un connettore. Usa l’account condiviso predefinito di quel connettore, a meno che non impostiaccount: <label>. Impostaaccountsolo quando un connettore contiene diversi account condivisi. Nella CLI,--account <label>lo imposta e--default-account(sutriggers set) lo cancella. Un’etichetta che non corrisponde a nessun account condiviso restituisceneeds_connectioncon il testo “Connect a shared<app>account labelled “<label>” on<connector>.“ - Un solo account alimentatore. Solo un account condiviso con il progetto e aperto all’intero progetto può alimentare un trigger. Un trigger viene eseguito senza che sia presente alcuna persona e i dati dell’evento finiscono nel prompt di una sessione. Un account condiviso solo con persone specifiche, o un account privato, non ne alimenta mai uno.
- Ogni evento si attiva una volta. Un trigger si attiva una volta per ogni evento del provider. Un evento riconsegnato non avvia una seconda sessione. Due trigger sullo stesso evento si attivano entrambi una volta.
- La pausa lo interrompe. Un trigger in pausa o un progetto in pausa ignora gli eventi. Gli eventi ignorati non vengono accodati.
- Le modifiche ricreano la sottoscrizione. La modifica di
connector,source,account,eventoconfigsostituisce la sottoscrizione. L’eliminazione del trigger lo rimuove.
Monitor
Sperimentale. I monitor vengono eseguiti solo dove è attivo il flag della funzionalità monitors. Il flag è disattivato per impostazione predefinita. Quando è disattivato, la piattaforma non esegue il provisioning di alcun ambiente monitor e non attiva alcun evento del monitor.
Un monitor osserva qualcosa che non invia webhook e non si adatta a una pianificazione: un log in tempo reale, la profondità di una coda, una pagina che cambia, un prezzo. Beeuni esegue il tuo comando 24/7 nell’ambiente monitor del progetto: una microVM persistente per progetto, con lo stesso limite di isolamento e gli stessi segreti del progetto di una sandbox di sessione. Il codice deterministico osserva; l’agente si attiva solo quando il comando emette una riga.
Quattro regole definiscono il contratto:
- Le righe di stdout sono eventi. Nient’altro lo è. Stderr contiene diagnostica: è visibile nei log del monitor, ma non attiva mai nulla.
- Ogni riga attiva il trigger esattamente una volta, attraverso il percorso già usato da un webhook:
filter→ modello del prompt →session_mode. - Un monitor non può fallire in silenzio. L’uscita del processo, l’esaurimento del budget di riavvio e un silenzio più lungo di
expect_event_withinattivano ciascuno un evento del ciclo di vita scritto dalla piattaforma nello stesso flusso. session_modeè impostato per impostazione predefinita sureusein un monitor, non sufresh. Un monitor si attiva ripetutamente per progettazione, quindifreshcreerebbe una sessione per ogni evento.
Aggiungi il 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 riesegue il comando ogni --interval e si aspetta che termini. --mode stream lo esegue una volta e lo mantiene attivo; un flusso non accetta alcun --interval. Entrambe le strutture producono righe e nulla a valle può distinguerle. Su un monitor, cron, run_at, timezone e secret_env vengono rifiutati.
Pubblicalo
beeuni shipLa piattaforma avvia l’ambiente monitor quando questa modifica arriva sul branch predefinito.
Conferma che sia in esecuzione
beeuni triggers ls
beeuni triggers info checkout-errorsls mostra la modalità e l’intervallo di un monitor, mentre un cron mostra la sua pianificazione. info mostra run, mode, interval e expect_event_within.
Limiti dei monitor
Ogni limite riportato di seguito è applicato dalla piattaforma.
| Limite | Valore |
|---|---|
| Monitor per progetto | 10 abilitati |
| Intervallo di polling | almeno 30 s |
expect_event_within |
almeno 5 min |
| Frequenza degli eventi per monitor | 60/ora sostenuti, burst di 30. Il superamento del limite sospende il monitor per 10 minuti; 3 sospensioni in 24 ore lo disabilitano. |
| Lunghezza della riga | 8 KiB, troncata con un marcatore truncated: true |
| Budget di riavvio | 5 riavvii / 10 minuti, poi un evento del ciclo di vita restart_budget_exhausted e un backoff di 15 minuti |
| Conservazione degli eventi | 30 giorni |
| Budget mensile dell’ambiente | 75 $ per impostazione predefinita. Una volta superato, l’ambiente si arresta e viene attivato un evento del ciclo di vita budget_exceeded. |
L’ambiente monitor necessita di un provider che supporti una sandbox persistente. Quando il provider del progetto non può mantenerne una, il flag monitors segnala che non è disponibile.
Struttura della configurazione
# 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
Un monitor sostituisce i campi della pianificazione con il relativo comando e la relativa struttura:
# 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 }}"
Un trigger di evento sostituisce i campi della pianificazione con l’app e l’evento monitorato. Vedi Trigger di eventi dell’app.
Il formato legacy beeuni.toml usa gli stessi campi in un contenitore diverso; vedi TOML legacy.
Campi
| Campo | Obbligatorio | Valore predefinito | Note |
|---|---|---|---|
slug |
sì | — | [a-z0-9][a-z0-9_-]{0,127}, univoco per progetto. |
type |
sì | — | cron, webhook o monitor. |
prompt |
sì | — | Stringa modello. Viene visualizzata come primo messaggio della sessione. |
name |
no | slug |
Etichetta leggibile. |
agent |
no | default_agent |
Deve indicare una chiave in agents:. Ometterla per usare default_agent; non scrivere il valore letterale default. |
model |
no | risolta al momento dell’attivazione | Formato wire provider/model, ad esempio anthropic/claude-sonnet-4-5. |
enabled |
no | true |
Se false, lo scheduler e il ricevitore webhook ignorano la voce. |
session_mode |
no | fresh o reuse per un monitor |
Vedi Strategia di sessione. |
session_id |
obbligatorio per pinned |
— | Sessione esatta a cui inviare di nuovo il prompt. |
session_key |
obbligatorio per keyed |
— | Stringa modello. Impostarla da sola implica session_mode: keyed. |
filter |
no | — | Percorso puntato → stringa prevista. Una consegna webhook non corrispondente restituisce 200 e non avvia alcuna sessione. |
cron |
uno tra cron/run_at, su type: cron |
— | Espressione a 6 campi: secondo, minuto, ora, giorno, mese, giorno della settimana. Si attiva al massimo una volta ogni 60 secondi; un’espressione più frequente non supera la convalida beeuni validate e l’API. |
run_at |
uno tra cron/run_at, su type: cron |
— | Timestamp ISO-8601. Si attiva una volta, poi resta inattivo. |
timezone |
no, solo cron | UTC |
Nome IANA. |
secret_env |
obbligatorio, solo webhook | — | Nome di un segreto del progetto che contiene la chiave di firma. Il segreto deve usare la consegna broker con il consumer connector. |
run |
obbligatorio, solo monitor | — | Comando relativo al repository le cui righe stdout sono gli eventi. Una riga, massimo 1024 caratteri. |
mode |
obbligatorio, solo monitor | — | poll esegue di nuovo run ogni interval; stream lo esegue una volta e lo mantiene attivo. |
interval |
obbligatorio per mode: poll |
— | Valore di durata (30s, 5m, 24h, 7d), minimo 30s. Non valido su mode: stream. |
expect_event_within |
no, solo monitor | — | Valore di durata, minimo 5m. Un silenzio più lungo di questo valore genera un evento del ciclo di vita. |
Un trigger cron richiede cron oppure run_at, mai entrambi. Un trigger webhook senza secret_env viene rifiutato: non esistono webhook non autenticati. Un monitor richiede run e mode e rifiuta senza eccezioni cron, run_at, timezone e secret_env: un manifest che dichiara una pianificazione che il runner del monitor non legge è una menzogna.
Configura il segreto di firma prima di creare o aggiornare un trigger webhook:
beeuni secrets set WEBHOOK_SECRET=-
beeuni secrets delivery WEBHOOK_SECRET broker --consumer connector
Passa il valore al primo comando tramite lo standard input. Se il segreto è stato usato in precedenza per la consegna sandbox, ruotalo dopo aver modificato la modalità di consegna, perché una sandbox esistente potrebbe conservare il valore precedente.
Strategia di sessione
session_mode controlla a quale sessione viene inviato di nuovo il prompt all’attivazione. Beeuni prova le modalità seguenti nell’ordine indicato e passa alla successiva in caso di errore.
pinned— invia di nuovo il prompt all’esattasession_id. Se la sessione non esiste più o è fallita, passa alla successiva.keyed— applica il rendering disession_keyal payload, quindi cerca la sessione più recente non fallita contrassegnata in precedenza con quella chiave esatta. Se la chiave risulta vuota o non ci sono sessioni corrispondenti, passa a una nuova sessione. Non passa mai alla sessione di un’altra chiave.reuse— invia di nuovo il prompt alla sessione più recente non fallita creata in precedenza da questo trigger. Anche un trigger con sessione fissata passa a questa modalità prima di continuare.fresh— crea una nuova sandbox e un nuovo branch. È l’impostazione predefinita e l’ultima alternativa per tutte le modalità. La nuova sessione diventa quella del trigger per le future attivazionireuseekeyed.
Una sessione reuse o keyed la cui cronologia non rientra più nel modello, nemmeno dopo la compattazione automatica, viene ritirata. L’attivazione successiva avvia una nuova sessione. Qualsiasi altro errore mantiene la sessione per l’attivazione successiva.
Un trigger cron frequente che non deve reinviare una cronologia in continua crescita può rinnovare la sessione in corrispondenza di un confine di calendario: session_key: "merge-{{ cron.scheduled_date }}" mantiene una sessione serializzata per giorno UTC e {{ cron.scheduled_hour }} una per ora UTC.
Esecuzioni non riuscite
Quando un’esecuzione avviata da un trigger termina con un errore, Beeuni lo registra nel trigger:
last_statusdiventafailedelast_errorcontiene il motivo, ad esempioOut of credits: Payment Required: Insufficient credits.- La pagina Schedule contrassegna il trigger con «L’ultima esecuzione non è stata completata» e mostra il motivo nel relativo pannello.
- Il proprietario dell’account riceve una notifica push sul cellulare al primo errore di esecuzione. Un errore successivo aggiorna il motivo senza inviare un’altra notifica.
- Il trigger resta
failedmentre continua ad attivarsi. Una nuova attivazione non dimostra che l’esecuzione funzioni.
La successiva esecuzione completata cancella l’errore. Un’esecuzione che interrompi tu, un subagent e una chiamata al modello ripetuta non costituiscono esiti di esecuzione. Un’attivazione che fallisce prima dell’avvio di un’esecuzione, ad esempio perché non è possibile creare una sessione, viene cancellata alla successiva attivazione riuscita.
Accesso alle sessioni
Per impostazione predefinita, le sessioni create da un trigger usano la policy privata. Ne è proprietario l’account di servizio dell’agente del trigger: l’identità di un agente è un principal service_account, quindi può possedere una sessione e avere assegnazioni come qualsiasi altro principal. Un project manager può sempre aprirle. Il proprietario e l’amministratore di un account hanno accesso equivalente a quello di un manager in ogni progetto, quindi lo stesso vale per loro. Chi ha configurato o attivato manualmente il trigger non ottiene accesso in virtù di tale azione, a meno che non ricopra uno di questi ruoli.
Le impostazioni del trigger offrono tre policy:
- Agente del trigger e project manager — nessun membro ordinario del progetto può aprire la sessione.
- Compagni di team selezionati — l’agente del trigger, i project manager e i membri selezionati del progetto o i gruppi dell’account.
- Intero progetto — tutti i membri del progetto.
Questa policy è un’impostazione di visibilità per singola risorsa applicata al modello dei ruoli, non un ruolo. Stabilisce chi può aprire le sessioni di un trigger. Non concede alcun permesso negato dalla valutazione dei ruoli. Vedi Account e accesso.
La policy di accesso è uno stato runtime locale all’account. Non viene inclusa nel manifest portabile beeuni.yaml perché gli ID dei principal appartengono a un singolo account. Usa la dashboard per configurarla.
Aggiornare solo questa policy non crea alcun commit Git. Salvare una policy aggiorna anche le sessioni precedenti create da quel trigger.
Una sessione fissata mantiene le proprie impostazioni di condivisione perché non è stata creata dal trigger. Se una sessione fissata non è disponibile e il trigger crea una sessione di ripiego, la policy del trigger si applica alla nuova sessione.
Modelli del payload
prompt e session_key vengono elaborati con lo stesso motore: {{ token.dotted.path }}. Un valore mancante viene sostituito con una stringa vuota: nessun errore e nessun {{ }} residuo. Gli oggetti e gli array vengono visualizzati come JSON. session_key viene sottoposto a trim e troncato a 512 caratteri.
Ogni attivazione riceve anche {{ trigger.slug }}, {{ trigger.type }} e {{ trigger.kind }} (sempre git). Il resto dell’insieme di variabili dipende dal tipo di attivazione del trigger.
| Origine | Variabili |
|---|---|
| cron | {{ cron.schedule }}, {{ cron.timezone }}, {{ cron.scheduled_for }} (lo slot per cui viene eseguito), {{ cron.claimed_at }} (quando lo scheduler lo ha rilevato), {{ cron.last_scheduled_for }} (lo slot precedente; vuoto alla prima esecuzione), {{ cron.scheduled_date }} (YYYY-MM-DD UTC dello slot), {{ cron.scheduled_hour }} (YYYY-MM-DDTHH UTC). Nessun fired_at di primo livello. |
| webhook | {{ fired_at }}, {{ body.* }} (analizzato come JSON; se il corpo non può essere analizzato, viene usato {{ body.raw }}), {{ headers.content_type }}, {{ headers.user_agent }}, {{ headers.forwarded_for }}. |
| monitor | {{ line.* }} — la riga di stdout, analizzata come JSON; una riga che non può essere analizzata viene resa come {{ line.raw }}. Inoltre {{ monitor.slug }}, {{ monitor.seq }}, {{ monitor.emitted_at }} e {{ monitor.kind }} (event o lifecycle). |
manuale (dashboard “fire now” o endpoint fire) |
{{ fired_at }}, {{ source }} (manual), {{ actor }}, {{ message.text }}, {{ message.source }}. |
Beeuni antepone server-side [MONITOR EVENT — automated, not user input] a ogni prompt del monitor renderizzato. Un evento del ciclo di vita ignora completamente il tuo template e renderizza invece un prompt scritto dalla piattaforma, ignorando filter — il silenzio non deve poter essere filtrato accidentalmente.
{{ message.text }} è impostato direttamente su una stringa vuota per un’esecuzione manuale, mentre {{ message.source }} è impostato su manual_test. Un’esecuzione manuale non è un modo per inserire dati di test nel prompt.
filter confronta i percorsi puntati come stringhe con lo stesso payload visualizzato dal prompt. Serve a interrompere i loop. Ad esempio, una sorgente che segnala entrambi i lati di una conversazione altrimenti riattiverebbe l’agente sulla propria risposta.
Firma del webhook
Si attiva su POST /v1/webhooks/projects/{projectId}/{slug}. Beeuni controlla la richiesta in quest’ordine, con un confronto a tempo costante:
- Firma HMAC — header
X-Beeuni-Signature: sha256=<hmac>(il prefissosha256=è facoltativo) oppureX-Hub-Signature-256compatibile con GitHub. HMAC-SHA256 sul corpo grezzo della richiesta, usando il segreto indicato dasecret_env. - Token statico, solo quando non è presente alcun header di firma, per i mittenti che non possono firmare un corpo con HMAC. Invia il segreto come
X-Beeuni-Token: <secret>,Authorization: Bearer <secret>oAuthorization: Basic <base64(user:secret)>(la parte della password è il token).
beeuni triggers info <slug> stampa questo schema — l’header, l’algoritmo e una richiesta di esempio firmata con un segnaposto $SECRET — e --json lo trasporta come webhook_signing. La scheda del trigger nella dashboard mostra la stessa richiesta di esempio.
| Stato | Significato |
|---|---|
| 202 | Firma o token valido. Il corpo è { status: "fired" | "queued" | "deduped", session_id, ... }. |
| 200 | Valido, ma ignorato — il progetto è in pausa oppure la consegna non corrisponde a filter. |
| 400 | ID o slug del progetto non valido nell’URL. |
| 401 | Firma e token sono entrambi assenti o errati. |
| 404 | Trigger non trovato, disabilitato, non è un webhook oppure il progetto non è attivo. |
| 409 | Il segreto di firma è assente, inattivo, non disponibile o non autorizza il consumer connector. La risposta include un codice webhook_secret_* e la procedura correttiva. |
| 500 | Autenticazione superata, ma la sessione non è stata avviata. |
Endpoint
| Metodo + percorso | Richiede | Note |
|---|---|---|
GET /v1/projects/{projectId}/triggers |
project.trigger.read |
Elenca i trigger, lo stato di runtime (last_fired_at, last_status, last_error, last_attempt_at) e gli errori di analisi del manifest. Una voce errata appare in errors[]; non interrompe gli altri trigger. |
POST /v1/projects/{projectId}/triggers |
project.trigger.create |
Crea un trigger. Esegue direttamente il commit nel manifest. |
PATCH /v1/projects/{projectId}/triggers/{slug} |
project.trigger.update |
Aggiornamento parziale, unito alla voce corrente. |
DELETE /v1/projects/{projectId}/triggers/{slug} |
project.trigger.delete |
Cancella anche lo stato di runtime del trigger. |
PATCH /v1/projects/{projectId}/triggers/activation |
project.trigger.update |
Corpo { paused: boolean }. Vedi Pausa e ripresa. |
POST /v1/projects/{projectId}/triggers/{slug}/fire |
project.trigger.fire |
Esecuzione manuale. Il ruolo integrato member del progetto dispone di project.trigger.fire, quindi un membro ordinario può eseguire un trigger. |
POST /v1/webhooks/projects/{projectId}/{slug} |
firma o token | URL pubblico, protetto dal segreto del webhook. |
Pausa e ripresa
Un interruttore a livello di progetto arresta contemporaneamente tutti i trigger del progetto, indipendentemente dal campo enabled di ciascun trigger. Durante la pausa, lo scheduler ignora il progetto e i webhook in ingresso restituiscono 200 con { status: "skipped" } — nesbeeuni sessione viene avviata. Un’esecuzione manuale continua a funzionare. Usalo quando lo stesso repository viene eseguito su due piani di controllo (ad esempio sviluppo e produzione), così cron non viene eseguito due volte. CLI: beeuni triggers pause e beeuni triggers resume. Vedi CLI per il gruppo completo di comandi beeuni triggers.
Limiti e affidabilità
- Lo scheduler esegue il polling circa ogni secondo (1.000 ms per impostazione predefinita; configurabile tramite
BEEUNI_TRIGGER_SCHEDULER_INTERVAL_MS). Un’esecuzione cron non inizia esattamente nel proprio slot: ogni trigger riceve un offset fisso fino a un quarto del proprio periodo, con un massimo di 30 minuti, quindi molti trigger impostati sullo stesso minuto non iniziano contemporaneamente. I dettagli del trigger eGET /triggers(next_fire_at) mostrano l’ora di inizio della prossima esecuzione. - Un’esecuzione non riuscita imposta lo stato precedente del trigger su failed, con l’errore. Questo vale per ogni sorgente: cron, manuale, webhook, evento dell’app e monitor. La prossima esecuzione riuscita cancella un’esecuzione non riuscita. Un’esecuzione non riuscita viene cancellata come descritto in Esecuzioni non riuscite.
- Ogni progetto consente, per impostazione predefinita, il provisioning simultaneo di 3 sessioni attivate. Un’esecuzione oltre tale limite restituisce
queued(202) invece di non riuscire e viene eseguita quando una di esse completa il provisioning. Non esiste un limite al numero di sessioni eseguite contemporaneamente. - Un’esecuzione manuale o webhook ha un timeout di 45 secondi. Il caricamento del manifest ha un timeout di 30 secondi.
- Un’esecuzione cron è associata allo slot di pianificazione dovuto, quindi un’esecuzione che è scaduta ma che in realtà è arrivata non viene duplicata al nuovo tentativo.
- Una consegna webhook viene eseguita una volta per evento. Beeuni legge l’ID evento da
X-Beeuni-Delivery-Id,X-GitHub-Delivery,X-Gitlab-Event-UUID,Linear-Delivery,webhook-idosvix-id, in quest’ordine; un nuovo tentativo con lo stesso ID restituisce202 { status: "deduped" }e non esegue nulla.X-Request-Idnon è un ID evento. Senza un ID evento, un corpo e una firma identici entro 10 minuti vengono considerati lo stesso evento; dopo tale intervallo viene eseguito nuovamente, quindi un job che invia lo stesso corpo statico a ogni deploy viene eseguito a ogni deploy. InviaX-Beeuni-Delivery-Idcon un nuovo valore per ogni evento (la richiesta di esempio usa$(uuidgen)). - Una consegna il cui tentativo precedente è fallito definitivamente (ad esempio perché l’account aveva esaurito i crediti) o la cui sessione è stata eliminata viene eseguita nuovamente quando viene riconsegnata con lo stesso ID. Un duplicato non modifica
last_fired_at.