External Triggers
External triggers let Holon agents wait for events from outside the runtime — for example, a CI pipeline completing, a GitHub webhook, or a timer firing. Every agent receives a default ingress callback URL at startup. The agent waits on it, and resumes when the external system delivers an event.
The trigger model
Holon treats external events as first-class runtime concepts. The model has three parts:
- Default ingress — Every agent receives a default ingress callback URL with a capability secret at startup.
- Wait on the trigger — The agent calls
WaitForwithwake=externaland the external object reference. The runtime records the wait and yields the turn. - External delivery — When the external system POSTs to the callback URL, the runtime wakes the agent and delivers the payload.
Delivery modes
Triggers support two delivery modes:
| Mode | Behavior |
|---|---|
enqueue_message | The external payload is enqueued as a normal message into the agent's queue |
wake_hint | The callback acts as a wake signal only; the agent resumes and checks the external state itself |
Use enqueue_message when the external system carries the full event content
(e.g., a webhook payload). Use wake_hint when the agent needs to actively
poll or check the external state after being woken (e.g., a CI status check).
Callback endpoints
Every agent has a single default ingress capability created at startup.
The default ingress is provisioned as either a wake_hint or enqueue_message
mode callback URL, depending on how the agent is configured. A trigger always
has one delivery mode and one trigger_url.
| Mode | URL pattern | Effect |
|---|---|---|
wake_hint | /callbacks/wake/:token | Wakes the agent from WaitFor(external) |
enqueue_message | /callbacks/enqueue/:token | Enqueues a message (the POST body) |
The callback token is a capability secret — treat it like a password. Anyone who knows the token can wake your agent or enqueue messages into it. Tokens are generated by the runtime, are cryptographically random, and are returned to the agent's execution environment context (not persisted to transcripts or logs by default).
Example: Wake callback
curl -X POST http://localhost:8787/callbacks/wake/CALLBACK_TOKEN
A minimal POST (even with an empty body) wakes the agent. The runtime validates the token and resumes the waiting agent.
Example: Enqueue callback
curl -X POST http://localhost:8787/callbacks/enqueue/CALLBACK_TOKEN \
-H "Content-Type: application/json" \
-d '{"text": "CI build #42 completed: success"}'
The payload is enqueued into the agent as a message. The agent processes it on its next turn.
The agent's WaitFor cycle
When an agent expects an external event:
- The agent uses its default ingress capability (exposed in the execution environment context)
- The agent calls
WaitFor(wake=external, resource=<object>) - The runtime records the wait, yields the turn, and the agent sleeps
- The external system delivers the event via the callback URL
- The runtime wakes the agent and resumes from the WaitFor point
The resource parameter in WaitFor identifies what the agent is waiting on
(e.g., github:owner/repo#123 for a PR, or a URL for an HTTP endpoint). This
is for the agent's own tracking; the runtime does not interpret it.
Security model
Callback tokens are capability secrets. The runtime stores only the hashed token, not the raw value — once a token is issued, the raw token is returned to the agent's execution context and is never persisted to logs or storage. Store it securely on the caller side.
Tokens can be revoked with CancelExternalTrigger. Revoking a trigger
invalidates its URL immediately; future requests to that URL are rejected.
Reset callback token
The POST /control/agents/:agent_id/external-triggers/:id/reset-callback
endpoint rotates the callback token for an existing trigger. The old token
is invalidated immediately and a new token is returned. Use this when a
token has been exposed or as a periodic security rotation.
Default ingress capability
Every agent has a default external ingress capability created at startup:
- A callback URL is available without explicit creation (the mode is determined by the agent's configuration)
- The default trigger ID and callback token are exposed in the agent's execution environment context
This default trigger is sufficient for most use cases. Use
CreateExternalTrigger only when you need a different delivery mode than the
default, or for compatibility diagnostics. Do not treat creating multiple
triggers as the ordinary workflow.
Cancelling triggers
Revoke a trigger when it's no longer needed:
CancelExternalTrigger { external_trigger_id: "trigger_abc123" }
This invalidates the callback URLs immediately. Any future requests to those URLs will be rejected.
Agent stop auto-revocation
When an agent is stopped (holon agent stop), all of its external triggers
are automatically revoked. This prevents orphaned callback URLs from
remaining active after the agent is no longer running. If you restart the
agent later, new triggers with fresh tokens are provisioned.
Integration patterns
CI/CD pipeline
Configure your CI system to POST to the wake callback on pipeline completion. The agent uses its default ingress, starts a build, waits on the trigger, and resumes when the build reports its status.
GitHub webhooks
Point a GitHub webhook at the enqueue callback. The agent receives repository events (issues, PRs, pushes) as enqueued messages and processes them on its next turn.
Scheduled timers
Holon's built-in Timer CLI command (holon timer --after-ms 60000) can
deliver events through the callback system, allowing agents to sleep and wake
on a schedule.
See also
- Integration guide — HTTP control plane endpoint reference
- Runtime model — How triggers fit into the agent execution loop
- WaitFor tool — The WaitFor tool that pairs with triggers
