Events and errors
Runtime event names, retry classification, provider backoff, and failure behavior.
Runtime events
RuntimeEvent.type is one of:
run.started,run.completed,run.failedretrieval.started,retrieval.completed,retrieval.failedmodel.started,model.completed,model.failedtool.started,tool.completed,tool.failedstep.started,step.completed,step.reused,step.failedchannel.eventoutput.queued,output.sent,output.skipped,output.failed
Every event includes agentId and timestamp, with optional run ID and bounded JSON data. Event handlers may be asynchronous, but should not become an unbounded blocking export path.
NoirError
throw new NoirError('Provider is rate limited', {
retryable: true,
retryAt: '2026-08-17T10:05:00.000Z',
code: 'provider_rate_limited',
cause: error,
})retryable controls whether the queue may try again. retryAt preserves provider backoff. code is a stable machine-readable classification. The message should be safe for logs but need not be sent directly to a user.
retryAtFromHeaders(headers) understands Retry-After seconds/date and X-RateLimit-Reset. Transient HTTP status classification includes 408, 409, 425, 429, and 5xx.
Tool failures
Malformed input, unauthorized effects, non-retryable provider errors, and repeated identical failures should terminate or route to a useful final response rather than loop. identicalToolFailureLimit prevents a model from calling the same failing operation indefinitely.
Delivery failures
Output failure is independent from model success. Retry transient channel errors through the outbox. Record a terminal failure after exhaustion and alert on it; never claim the person received a response merely because text was generated.