Skip to content

Read Native Sheet Inputs in a Model

Use NativeSheetReader when Python model code consumes cells from a committed Native Sheet. It distinguishes a missing cell, a literal blank, a formula without a cached value, a formula error, and numeric zero. Directly loading a .btsheet.json file bypasses these checks and does not emit the canonical cell identities used for lineage reconciliation.

Download the immutable native_sheet_reader.py v1.0.0 source from Bridge Town’s public GitHub release. Its SHA-256 digest is 9849fff47d88d8ef15642d3825e69cd95ebfedd0c564b274d949aff3173ad8f5. The release includes the complete SHA256SUMS, source at the immutable tag, runnable example, changelog, MIT license, and ownership record.

Verify the file outside the network-isolated model sandbox:

Terminal window
curl -fL -o native_sheet_reader.py \
https://github.com/Bridge-Town/financial-modeling-mcp/releases/download/model-authoring-helpers-v1.0.0/native_sheet_reader.py
printf '%s %s\n' \
9849fff47d88d8ef15642d3825e69cd95ebfedd0c564b274d949aff3173ad8f5 \
native_sheet_reader.py | sha256sum --check

Copy the verified file byte-for-byte into the model repository as lib/native_sheet_reader.py with create_file or commit_files. The helper uses only Python’s standard library and makes no network calls.

Import the helper from a model file and use it as a context manager:

from lib.native_sheet_reader import NativeSheetReader
with NativeSheetReader() as sheets:
base_revenue = sheets.read_value("sht_inputs", "tab_drivers", "B2")
growth_rate = sheets.read_value("sht_inputs", "tab_drivers", "B3")
result = {
"next_period_revenue": round(float(base_revenue) * (1 + float(growth_rate)), 2)
}

Use the canonical sheet_id and tab_id returned by get_native_sheet. A tab’s exact display name is also accepted, but telemetry always records its stable tab_id. A1 references are normalized to uppercase.

After a successful with block, the helper writes /outputs/native_sheet_read_set.json. The artifact contains only bounded sheet_id/tab_id/cell_ref identities and read-status labels — never cell values. Repeated reads are deduplicated, the default maximum is 1,000 entries, and truncation is explicit.

read_value is intentionally strict: a missing cell, literal blank, formula without a cached value, or formula error raises a specific exception rather than substituting zero. When a literal blank has business meaning, call read_cell and branch on its status:

from lib.native_sheet_reader import NativeSheetReader
with NativeSheetReader() as sheets:
optional_bonus = sheets.read_cell("sht_inputs", "tab_drivers", "B4")
bonus = 0.0 if optional_bonus.status == "literal_blank" else float(optional_bonus.value)

Do not catch the base exception and continue with an invented value. Formula cache and error failures mean the sheet must be fixed and recalculated before the model runs.

The read-set artifact says which canonical cells the model read. To explain how an input drives an output, install the separately versioned output_lineage.py helper and pass the same sheet_id, tab_id, and cell_ref through InputSourceRef when building the output trace.