Agent serves an HTTP webhook and runs your handler once per dispatch. It runs
under an active execution context, so defineTool,
rebunoFetch, and step() record durably.
The handler
The handler is the async function you hand toagent.serve() or agent.bind(),
named process in the examples below. It takes one argument, the execution’s
input object, passed through unchanged:
output and has to be
JSON-serializable.
Validating input
Pass aninputSchema, any Standard Schema
validator such as Zod, Valibot, or ArkType, to validate and coerce input:
inputSchema, input is passed through as-is.
serve() vs fetch
serve() binds the handler and serves it with node:http. It blocks, resolving
only when the server closes:
agent.fetch to mount the agent into an existing service or an edge
runtime. It is a Web-standard (Request) => Promise<Response> handler with the
webhook logic already wired:
agent.fetch reads the request body, verifies the signature, and returns the
response, so it doesn’t care what server calls it. agent.serve is a thin
node:http wrapper around it.
Dispatch and resume
Each webhook POST carries anexecution_id, a dispatch_id, and a
dispatch_attempt. The agent:
- Verifies the
Rebuno-Signatureheader (see Signing). A bad or missing signature gets a401. - Acknowledges immediately. The handler runs in a background task and the
webhook returns
200right away, so delivery isn’t held open for the whole execution. - Aborts the handler still running for that execution when the webhook supersedes it, so a re-delivery doesn’t leave two copies racing. The superseded run’s kernel client is scoped to the aborted signal, so it can neither renew the lease nor write for a dispatch it no longer owns. A repeat of the attempt already running, or of one the kernel has moved past, is ignored.
- Skips terminal executions. Nothing to do if it is already
completed,failed, orcancelled. - Runs. It fetches the execution’s input, validates it, and calls your handler under the ambient execution context.
Blocked or Terminated your handler swallows still ends the dispatch
correctly, because the execution context remembers it and Agent re-throws it.
A denial or rate limit has no such backstop and has to escape the handler, but it
may arrive wrapped in a provider SDK’s own error type, which raiseForRefusal()
unwraps.
What happens on failure
The agent maps outcomes from your handler onto the execution:
See Errors for what each class means.
Lifecycle
serve() keeps running until the server closes. Call these directly only when
you drive agent.fetch yourself and want to drain in-flight handlers before
shutdown.