API Overview¶
TopoExec's public C++ surface is split into runtime/YAML targets, with optional preview targets for adapters, FFI, CLI-backed Python automation, and trusted-native plugin loading:
topoexec::runtime: component, graph model, channel, scheduler, runtime runner, metrics, trace, and the C++ graph builder.topoexec::yaml: optional YAML graph loading and JSON plan rendering helpers.topoexec::c_api: optional unstable C API/FFI preview over a small runtime subset. It is default-off and ABI version0.topoexec_preview: optional stdlib-only Python package that shells out to the CLI for validate/plan/run/metrics/trace automation. It is default-off and not a native extension.topoexec::plugin_loader: optional trusted-native dynamic component loader preview. It is default-off, manifest/version checked, and not sandboxed or ABI-stable.
Use topoexec::runtime when an application builds GraphSpec directly in C++ and does not need YAML parsing.
For stability categories and lifecycle failure behavior, see public-api.md. For generated public-header lookup, see doxygen.md; Doxygen is optional API reference, not the semantic source of truth. For the C API/FFI preview, see c-api.md. For the Python automation preview, see python-preview.md. For the dynamic plugin loader preview, see plugin-loader.md. For payload ownership and typed access helpers, see payloads.md.
Minimal Runtime Shape¶
Application code usually provides three pieces:
Componentsubclasses with descriptors andexecute()implementations.- A
ComponentRegistrymapping descriptor types to factories. - A
GraphSpec, either built directly in C++ or loaded through the optional YAML helpers.
The C++ builder API in topoexec/runtime/graph_builder.hpp is a thin convenience layer over GraphSpec. It does not hide the runtime model or introduce a second graph representation.
auto graph = topoexec::GraphBuilder("pipeline")
.event_loop_lane("main")
.component(topoexec::component_node(
"source", "app.Source", {topoexec::manual_event_source()},
topoexec::manual_trigger(), topoexec::lane_execution("main")))
.component(topoexec::component_node(
"sink", "app.Sink", {topoexec::message_event_source({"in"})},
topoexec::any_input_trigger({"in"}), topoexec::lane_execution("main")))
.edge(topoexec::immediate_edge("source_sink", "source.out", "sink.in"))
.build();
examples/apps/cpp_builder_minimal is the runnable version of this pattern and links only topoexec_runtime.
Failure Reporting¶
The original void lifecycle and execute() hooks remain supported. Components may also override status-returning hooks such as execute_status() to report failures without throwing:
topoexec::Status execute_status(const topoexec::Invocation& invocation,
topoexec::GraphContext& ctx) override {
if (invocation.payload == nullptr) {
return topoexec::Status::error("missing payload");
}
return topoexec::Status::success();
}
RuntimeRunnerResult::runtime_errors records configure, activate, restore,
reset, execute, snapshot, and deactivate failures with structured phase,
component id, code, message, trace id, and fatality fields. Started components
are deactivated on stop and component error paths.
Payload Access¶
Components should prefer typed helpers over manual std::variant access:
const auto& text = invocation.payload_as<topoexec::TextPayload>();
const auto* frame = invocation.try_payload_as<topoexec::FrameView>();
Bad typed access raises a clear std::runtime_error; status-returning components can translate that into Status::error(...).