Distilled from the brainstorming notes below. These are the decisions we landed on, ready to be turned into GitHub issue specs.
my_model.run().get_outputs()). Accessor functions are used to pull data out.pd.Series (preserves the index); multiple outputs return a pd.DataFrame."s" (second) precision, since Kalix supports timesteps down to 1 second (but no smaller). Can be converted to "ns" downstream if needed.patch(), which updates the relevant parts of the DOM and re-parses/re-validates the whole model. Crude relative to dedicated accessors, but robust, powerful, and requires no extra maintenance as the model object grows richer. Accessors may come later.import kalix
# Load a model directly from a file
my_model = kalix.load_file("model_file.ini")
# Create an empty model, then populate it
my_model = kalix.new_model()
my_model.load_file("model_file.ini")
# Load a full model from a string
my_model.load_string(whole_model_string)
# Load a partial model (snippet) from a string
my_model.load_string(snippet_string, snippet=True)
# run() returns the model (to support chaining), NOT results directly
my_model.run()
# Retrieve outputs after running
results_df = my_model.run().get_outputs()
# All outputs -> pd.DataFrame
results_df = my_model.get_outputs()
# Single output -> pd.Series (index preserved)
x = my_model.get_outputs("node.my_dam.volume")
# Multiple outputs -> pd.DataFrame
y = my_model.get_outputs(["node.my_dam.volume", "node.my_dam.level"])
Models are edited by applying an INI snippet via patch(). The snippet is merged into the DOM and the whole model is re-parsed and re-validated.