Events are the real-time signal stream for a run. They appear in the run detail view and feed into alerts and reports.
Emit events via run.emit(type, payload, level) or the built-in helpers.
| Level | When to use |
|---|---|
debug | Verbose tracing, internal state |
info | Normal progress (default) |
warn | Something unexpected but recoverable |
error | A failure occurred |
These types are understood by AgentOS and rendered with dedicated UI in the run detail view.
run.emitLLMRequest("claude-sonnet-4-6", "Summarise this document...");
run.emitLLMResponse("claude-sonnet-4-6", "The document covers...", {
input_tokens: 512,
output_tokens: 128,
});
| Type | Payload fields |
|---|---|
llm.request | model, prompt, any extras |
llm.response | model, response, input_tokens?, output_tokens? |
run.emitToolCall("search_web", { query: "latest AI news" });
run.emitToolReturn("search_web", { results: [...] });
run.emitToolError("search_web", "Timeout after 5s");
| Type | Payload fields |
|---|---|
tool.called | tool, input |
tool.returned | tool, output |
tool.failed | tool, error |
Use any dot-separated string as a type. Convention: noun.verb.
run.emit("invoice.validated", { invoiceId: "INV-001", amount: 1250.00 });
run.emit("retry.attempted", { attempt: 2, maxAttempts: 3 }, "warn");
run.emit("external_api.failed", { endpoint: "/payments", status: 503 }, "error");
Good naming examples:
document.parsedstep.started / step.completedcache.hit / cache.missapproval.requestedEvents are buffered client-side and flushed every 500ms or when the batch reaches 50 events. You don't need to manage this — run.complete() and run.fail() always flush before closing the run.
Call run.flush() explicitly if you need to force a flush mid-run (e.g. before a long blocking operation).