bazel.build_events.iterator(), pass it to ctx.bazel.build() (or ctx.bazel.test()) via the build_events parameter, and then iterate the handle with for event in events:. Events are delivered synchronously (Starlark is single-threaded), so the iterator blocks until the next event is ready and unblocks when the build finishes.
Each event has a kind string that identifies the event type, and a payload whose fields depend on that kind. The full set of event kinds and payload types is defined in Bazel’s Build Event Stream protocol.
Build Event Stream reference
- Protocol definition: build_event_stream.proto
- API documentation: Buf Schema Registry
- Event ordering examples: Bazel BEP Documentation
- AXL type reference: build_event kinds
Collecting output files
A common use case is collecting the output files that Bazel produced. Files arrive innamed_set_of_files events:
File payload exposes name, digest, length, and path_prefix directly. The URI is wrapped in a file oneof (uri, contents, or symlink_target_path) — most consumers want name, which is the file’s logical identifier (for example bazel-bin/path/to/target.out).
Filtering by event kind
To skip irrelevant events, passkinds= to iterator(). Only the listed event kinds are delivered:
Reacting to test results
test_result events fire once per test target. The label of the test target is on the event’s id, and the status comes from the payload:

