Skip to content
AGH RuntimeAutomation

Triggers

Configure AGH automation triggers that react to runtime events, filters, and prompt templates.

Audience
Operators running durable agent work
Focus
Automation guidance shaped for scanability, day-two clarity, and operator context.

Triggers run agents in response to events. They are useful when the next agent run should depend on something that happened inside AGH, such as a session stopping, a memory consolidation completing, or a webhook delivery arriving.

Triggers do not bind to jobs by ID. A trigger is its own automation definition with an event, filters, agent, prompt template, retry policy, and fire limit. When a matching event arrives, AGH uses the same dispatcher and run history model that scheduled jobs use.

Trigger fields

FieldRequiredMeaning
nameYesHuman-readable trigger name.
scopeYesglobal or workspace.
workspace / workspace_idWorkspace triggers onlyTOML uses workspace; API payloads and stored triggers use workspace_id.
eventYesEvent name to match. Built-in events are documented below, and extension events use ext.*.
agent / agent_nameYesAgent to run when the trigger matches.
promptYesGo text/template rendered against the activation envelope.
filterNoExact-match conditions on envelope fields.
enabledNoDefaults to true for parsed config definitions.
retryNoSame retry policy as jobs. Defaults to none.
fire_limitNoSame rolling fire limit as jobs. Defaults to 12/1h unless changed.
endpoint_slugWebhook triggersHuman-readable webhook endpoint segment.
webhook_secret_refWebhook triggersenv:NAME or vault:automation/... ref for the webhook signing secret.

Event types

AGH stores trigger events as strings. The current runtime emits these built-in event names:

EventSourceTypical use
session.createdSession lifecycle observerStart a helper agent when a workspace session begins.
session.stoppedSession lifecycle observerSummarize work, collect failures, or schedule follow-up review.
memory.consolidatedMemory consolidation runtimeReview durable memory changes after consolidation.
hook.<hook_name>.completedHook runtimeContinue a workflow after a named hook completes.
webhookSigned HTTP webhook ingressReact to CI, deploy, incident, or repository events from external systems.
ext.*Extension trigger APILet an extension publish its own automation event family.

The event name must be non-empty. AGH does not restrict custom extension event names beyond the extension ingress contract.

Matching and filters

A trigger fires only when all of these match:

  • the trigger is enabled
  • the trigger event equals the activation event
  • the trigger scope equals the activation scope
  • workspace triggers match the same workspace ID
  • every filter entry matches exactly

Filters support these paths:

Filter pathMatches
kindActivation event name such as session.stopped, webhook, or ext.release.
scopeglobal or workspace.
workspace_idWorkspace ID carried by the activation envelope.
sourceActivation source such as observer, hook, webhook, or extension.
data.<path>String value inside the activation data object.

Filter values must be non-empty strings.

filter = { "data.stop_reason" = "error", "data.agent_name" = "codex" }

Prompt templates

Trigger prompts are rendered with Go text/template. The template data is the activation envelope:

Template valueMeaning
.KindActivation event name.
.Scopeglobal or workspace.
.WorkspaceIDWorkspace ID for workspace-scoped activations.
.SourceActivation source such as observer, hook, webhook, or extension.
.DataEvent-specific data map.

Use index for dynamic data keys:

prompt = "Summarize session {{ index .Data \"session_id\" }}. Stop reason: {{ index .Data \"stop_reason\" }}."

Invalid templates fail validation when the trigger is created or loaded from config.

Worked example: summarize failed sessions

This trigger runs after a workspace session stops with an error. The prompt template receives the event data and turns it into a targeted summarization request.

[[automation.triggers]]
scope = "workspace"
workspace = "/Users/you/src/checkout-api"
name = "summarize-failed-sessions"
event = "session.stopped"
agent = "summarizer"
prompt = "Summarize session {{ index .Data \"session_id\" }}. Stop reason: {{ index .Data \"stop_reason\" }}."
filter = { "data.stop_reason" = "error" }
retry = { strategy = "backoff", max_retries = 2, base_delay = "5s" }
fire_limit = { max = 4, window = "1h" }

Create the same dynamic trigger from the CLI:

agh automation triggers create \
  --name summarize-failed-sessions \
  --scope workspace \
  --workspace /Users/you/src/checkout-api \
  --event session.stopped \
  --agent summarizer \
  --prompt 'Summarize session {{ index .Data "session_id" }}. Stop reason: {{ index .Data "stop_reason" }}.' \
  --filter data.stop_reason=error \
  --retry backoff:2:5s

API example

Create a dynamic trigger over HTTP:

curl -sS -X POST http://localhost:2123/api/automation/triggers \
  -H "Content-Type: application/json" \
  --data '{
    "name": "memory-review",
    "scope": "workspace",
    "workspace_id": "ws_123",
    "event": "memory.consolidated",
    "agent_name": "reviewer",
    "prompt": "Review memory consolidation {{ index .Data \"consolidation_id\" }}.",
    "filter": {
      "data.scope": "workspace"
    },
    "retry": {
      "strategy": "none"
    },
    "fire_limit": {
      "max": 3,
      "window": "1h"
    },
    "enabled": true
  }'

The response is wrapped as:

{
  "trigger": {
    "id": "trg_...",
    "name": "memory-review",
    "event": "memory.consolidated",
    "enabled": true
  }
}

Conditional execution

Filters handle exact-match conditions. For richer policy, use lifecycle hooks around automation runs:

  • job or trigger pre-fire hooks can rewrite the prompt
  • pre-fire hooks can cancel the run, which records the run as canceled
  • run-failed hooks receive retry metadata, including whether AGH will retry

Hooks are part of the same runtime flow, so cancellation and prompt changes are visible in run history.

Monitoring trigger runs

Read trigger-specific history:

agh automation triggers history <trigger-id> --last 20

Read all recent automation runs for a status:

agh automation runs --status failed --last 20

Query the API:

curl -sS "http://localhost:2123/api/automation/triggers/<trigger-id>/runs?limit=20"

Run statuses are the same statuses documented for jobs: scheduled, running, delegated, completed, failed, and canceled.

On this page