vtcode-exec-events
February 25, 2026 · View on GitHub
The vtcode-exec-events crate packages the execution telemetry schema that powers VT Code's
automation timeline. Downstream applications can depend on this crate to deserialize
thread progress, command execution lifecycle updates, and tool activity without pulling in
the rest of vtcode-core.
Event taxonomy
Events are serialized with serde using an externally tagged ThreadEvent enum. Each
variant captures a specific moment in the lifecycle of an execution thread:
- Thread lifecycle –
thread.started,turn.started,turn.completed, andturn.failedevents communicate coarse-grained scheduling milestones including token accounting through theUsagestruct.F:vtcode-exec-events/src/lib.rs†L12-L63 - Timeline items – item events wrap a
ThreadItemsnapshot with stable identifiers so consumers can correlate incremental updates (item.started,item.updated) with their eventual completion (item.completed).F:vtcode-exec-events/src/lib.rs†L65-L120 - Command execution –
CommandExecutionItemreports the command string, aggregated output, exit status, and a tri-stateCommandExecutionStatusso dashboards can surface long-running processes and failures.F:vtcode-exec-events/src/lib.rs†L122-L160 - File changes –
FileChangeItemenumerates per-file updates with aPatchApplyStatusoutcome to indicate whether patches landed cleanly.F:vtcode-exec-events/src/lib.rs†L162-L200 - Tooling and search –
McpToolCallItemandWebSearchItemtrack external tool invocations and provider metadata, including optional arguments and raw result payloads for audit trails.F:vtcode-exec-events/src/lib.rs†L202-L240 - Errors –
ThreadErrorEventandErrorItemrecord terminal failures alongside the human-readable messages surfaced to operators.F:vtcode-exec-events/src/lib.rs†L41-L44F:vtcode-exec-events/src/lib.rs†L242-L248
The schema favors additive evolution: new fields default via Option or #[serde(default)]
so older consumers continue to deserialize previously known structures.
Versioning and compatibility
The crate follows semantic versioning. Backwards-compatible additions (such as new event
variants or optional fields) result in a minor version bump, while any breaking schema
changes trigger a major release. The ThreadEvent enum is stringly tagged using
snake-cased identifiers (for example, item.updated), which makes diffing JSON logs and
indexing metrics straightforward. Consumers should pin to compatible minor versions when
building dashboards to avoid accidental breakage.
Every serialized stream can opt into metadata that advertises the schema version through
the VersionedThreadEvent wrapper and the EVENT_SCHEMA_VERSION constant. Downstream
pipelines can gate deserialization or migrations using this metadata before materializing
individual events.F:vtcode-exec-events/src/lib.rs†L8-L44F:vtcode-exec-events/src/lib.rs†L270-L308
Feature flags
vtcode-exec-events ships with feature toggles so applications can pick the supporting
infrastructure they need:
serde-json(default) – enables helper functions for serializing/deserializing events to JSON strings or values while preserving the existing ergonomic API.F:vtcode-exec-events/src/lib.rs†L70-L92telemetry-log– provides a ready-madeLogEmitterthat writes JSON payloads through thelogfacade so adopters can reuse existing logging pipelines.F:vtcode-exec-events/src/lib.rs†L94-L133telemetry-tracing– exposes aTracingEmitterthat emits structured events tagged with the schema version, integrating directly with thetracingecosystem.F:vtcode-exec-events/src/lib.rs†L135-L187schema-export– produces JSON Schema documents for both raw and versioned events so downstream services can validate telemetry payloads offline.F:vtcode-exec-events/src/lib.rs†L189-L200
Integrating with VT Code runtimes
vtcode-core re-exports the schema and emits events from the ExecEventRecorder inside the
agent runner. You can attach an event sink by supplying a closure when constructing the
runner, enabling streaming telemetry or custom logging pipelines.F:vtcode-core/src/core/agent/runner.rs†L42-L87 The recorder
invokes the sink for every serialized ThreadEvent, including streaming message deltas and
command status transitions.F:vtcode-core/src/core/agent/runner.rs†L89-L154
A minimal consumer might look like the following:
use std::sync::{Arc, Mutex};
use vtcode_core::core::agent::runner::AgentRunnerBuilder; // hypothetical helper
use vtcode_exec_events::ThreadEvent;
let sink = Arc::new(Mutex::new(Box::new(|event: &ThreadEvent| {
println!("{}", serde_json::to_string(event).expect("serialize"));
}) as Box<dyn FnMut(&ThreadEvent) + Send>));
let runner = AgentRunnerBuilder::default()
.with_event_sink(sink)
.build()?;
runner.execute().await?;
Downstream services can forward the JSON payloads to observability stacks, persist them for postmortems, or feed them into realtime dashboards.
The crate also publishes reusable emitters so integrations can skip wiring boilerplate. For example, the logging emitter can be attached directly to the runner:
use vtcode_exec_events::LogEmitter;
let mut emitter = LogEmitter::default();
runner.set_event_handler(move |event| emitter.emit(event));
When using the tracing feature, substitute TracingEmitter::default() to forward the
structured payloads into tracing subscribers with automatic schema-version tagging.
Bridging vtcode-bash-runner
Enabling the exec-events feature in vtcode-bash-runner exposes an
EventfulExecutor wrapper that converts each shell invocation into
ThreadEvent updates. This lets downstream adopters reuse the same telemetry
vocabulary when commands run outside VT Code's core runtime—for example, when
shell actions are executed via the standalone runner in CI or automation
pipelines. Wrap any executor and provide an emitter to mirror command activity:
use vtcode_bash_runner::{BashRunner, EventfulExecutor, ProcessCommandExecutor};
use vtcode_exec_events::LogEmitter;
let executor = EventfulExecutor::new(ProcessCommandExecutor::new(), LogEmitter::default());
let policy = vtcode_bash_runner::AllowAllPolicy;
let mut runner = BashRunner::new(workspace_root.clone(), executor, policy)?;
runner.ls(None, false)?;
Each invocation emits item.started and item.completed events with aggregated
output and exit codes, so telemetry consumers receive the same stream whether
commands originate from VT Code's agent loop or the extracted runner crate.F:vtcode-bash-runner/src/executor.rs†L358-L470
Examples
The repository ships with a runnable example that emits a short execution timeline and
exports each ThreadEvent as JSON Lines. Running the example prints both the serialized
events and a derived summary of completed commands:
cargo run -p vtcode-exec-events --example event_timeline
The source (vtcode-exec-events/examples/event_timeline.rs) demonstrates how to
construct timeline events, serialize them with serde_json, and post-process the
sequence to build command summaries outside of VT Code's runtime.
Next steps
With schema metadata, feature-gated emitters, and documentation updates in place, the
vtcode-exec-events extraction tasks are complete. The remaining work in the component
extraction initiative is to execute the staged publishes outlined in the release plan and
close out the dependency bump follow-ups.