Innovate R kernel bindings

This vignette shows how the innovate.R package acts as a thin R interface to the Innovate functional kernel. The examples are designed to build without network access. Chunks that invoke the Python bridge are guarded and run only when INNOVATE_R_VIGNETTE_RUN_KERNEL=true.

Installation

Install the R binding from a local checkout or from a prepared package artifact. The binding also needs a Python environment containing the innovate Python package. In a repository checkout, the bridge can use the local src/ tree.

install.packages("bindings/r", repos = NULL, type = "source")
Sys.setenv(INNOVATE_PYTHON_COMMAND = "uv")

For a system Python launcher instead of uv, point the binding at python3:

Sys.setenv(INNOVATE_PYTHON_COMMAND = "python3")

The schema version is available without contacting the bridge:

kernel_schema_version()
#> [1] "1.0"

Backend Discovery

Model and backend discovery is provided by the stable kernel operation discover_models. This live call is disabled by default for vignette builds.

models <- kernel_discover_models()
head(models[, c("key", "family", "supported_backends", "supports_simulation")])

When writing portable code, treat discovery as data. For example, select models that advertise simulation support before constructing simulation requests:

simulation_models <- subset(models, supports_simulation)
simulation_models$key

Core Request Examples

The R binding builds versioned request envelopes and sends them to the shared kernel. Request construction is local R work and is safe to run during vignette builds.

fit_request <- kernel_request(
  operation = "fit_model",
  model_key = "bass",
  payload = list(
    inputs = list(
      time = c(0, 1, 2, 3, 4),
      observed = c(0.01, 0.04, 0.11, 0.23, 0.38)
    ),
    model_kwargs = list()
  )
)

fit_request$operation
#> [1] "fit_model"
fit_request$model_key
#> [1] "bass"
fit_request$schema_version
#> [1] "1.0"

Run the fit through the bridge only in an environment that has the Python kernel available:

fit_result <- kernel_fit_model(fit_request)
fit_result

Prediction and simulation use the same envelope pattern. A fitted-state payload can be supplied directly when you already have parameters.

predict_request <- kernel_request(
  operation = "predict_model",
  model_key = "bass",
  payload = list(
    state = list(
      model_key = "bass",
      model_name = "BassModel",
      constructor_kwargs = list(),
      parameters = list(p = 0.03, q = 0.38, m = 120),
      predict_kwargs = list()
    ),
    inputs = list(time = c(0, 1, 2, 3, 4))
  )
)

predict_request$payload$state$parameters
#> $p
#> [1] 0.03
#> 
#> $q
#> [1] 0.38
#> 
#> $m
#> [1] 120
kernel_predict_model(predict_request)
simulate_request <- kernel_request(
  operation = "simulate_model",
  model_key = "bass",
  payload = predict_request$payload
)

simulate_request$operation
#> [1] "simulate_model"
kernel_simulate_model(simulate_request)

Diagnostics

Diagnostics use the same fitted-state convention plus observed values. The helper kernel_extract_diagnostics() works on list-like kernel results that include diagnostics fields.

diagnose_request <- kernel_request(
  operation = "diagnose_model",
  model_key = "logistic",
  payload = list(
    state = list(
      model_key = "logistic",
      model_name = "LogisticModel",
      constructor_kwargs = list(),
      parameters = list(L = 100, k = 0.65, x0 = 3),
      predict_kwargs = list()
    ),
    inputs = list(
      time = c(0, 1, 2, 3, 4, 5),
      observed = c(12.4, 21.4, 34.3, 50.0, 65.7, 78.6)
    )
  )
)

diagnose_request$model_key
#> [1] "logistic"
diagnostics_result <- kernel_diagnose_model(diagnose_request)
kernel_extract_diagnostics(diagnostics_result)

The extraction helper intentionally fails when the result does not expose diagnostics:

tryCatch(
  kernel_extract_diagnostics(list(values = c(1, 2, 3))),
  error = conditionMessage
)
#> [1] "Kernel result does not expose diagnostics"

Guarded Failure Modes

The binding performs local request validation before bridge invocation. Kernel operations other than discover_models require a model key.

tryCatch(
  kernel_request(operation = "predict_model", payload = list()),
  error = conditionMessage
)
#> [1] "Kernel operation 'predict_model' requires a model_key"

Kernel error payloads are converted into an innovate_kernel_error condition so callers can catch kernel failures without parsing transport output.

condition <- tryCatch(
  kernel_response_to_r(list(
    schema_version = "1.0",
    operation = "predict_model",
    result = NULL,
    error = list(
      code = "unsupported_native_operation",
      message = "Native execution is not available for this payload"
    ),
    metadata = list()
  )),
  error = identity
)

inherits(condition, "innovate_kernel_error")
#> [1] TRUE
condition$message
#> [1] "Native execution is not available for this payload"

Bridge execution can also fail if the Python command is unavailable or the Python environment cannot import the kernel. Keep live calls guarded in reproducible documents and surface the configured launcher in logs:

Sys.getenv("INNOVATE_PYTHON_COMMAND", "uv")
kernel_discover_models()