Use this when an Inngest function needs formula-backed business logic, but the
calculation should be one durable step.run() boundary instead of spreadsheet
UI automation or ad hoc formula code.
Inngest owns event delivery, durable step execution, retries, run history, and observability. Bilig owns formula workbook state, recalculation, JSON serialization, restore, and readback proof.
Official Inngest references:
The runnable source lives in:
examples/inngest-workpaper-step
It contains:
src/inngest-workpaper-function.ts for the Inngest function wrappersrc/workpaper-quote.ts for the pure WorkPaper formula calculationsrc/smoke.ts for local no-account proofscripts/check-inngest-recipe.ts for static recipe checksRun the proof locally:
cd examples/inngest-workpaper-step
pnpm install --ignore-workspace --lockfile=false
pnpm run check
pnpm run typecheck
pnpm run smoke
The smoke edits Inputs!B2, recalculates quote formulas, serializes the
WorkPaper document, restores it, verifies restored calculated values match, and
prints JSON.
The checked-in function wrapper uses step.run() as the durable formula
boundary:
import { Inngest } from 'inngest'
import { calculateWorkPaperQuote } from './workpaper-quote.js'
export const inngest = new Inngest({ id: 'bilig-workpaper-example' })
export const calculateWorkPaperQuoteFunction = inngest.createFunction(
{
id: 'bilig-workpaper-quote',
retries: 3,
triggers: [{ event: 'bilig/quote.requested' }],
},
async ({ event, step }) => {
const result = await step.run('calculate-workpaper-quote', async () => calculateWorkPaperQuote(event.data))
if (!result.proof.verified) {
throw new Error('WorkPaper proof failed')
}
return result
},
)
The helper imports @bilig/workpaper, writes one input, recalculates formulas,
exports WorkPaper JSON, restores the document, and returns a compact
serializable patch plus proof.
The proof contains:
{
"patch": {
"subtotal": 2250,
"discount_amount": 225,
"taxable_amount": 2025,
"tax_amount": 162,
"total": 2187,
"margin_amount": 1089
},
"proof": {
"editedCell": "Inputs!B2",
"before": {
"total": 1458
},
"after": {
"total": 2187
},
"afterRestore": {
"total": 2187
},
"verified": true
}
}
Use patch for app writeback. Keep proof in logs, run metadata, an audit
table, or object storage when the business workflow needs evidence.
Before using this pattern for customer-critical workflows:
@bilig/workpaper, XLSX import/export, file I/O, and object-store
writes inside step.run() handlers or service helpers they call.Use it for quote approvals, pricing rules, payout checks, import validation, order-review gates, and durable AI workflow steps where spreadsheet formulas are the most reviewable representation of business logic.
Do not use it to pretend Bilig is desktop Excel. Use Inngest for durable
execution, step.run() for the retriable formula boundary, and external oracles
for Excel-specific behavior.
If this is shared in an Inngest issue, discussion, or docs proposal, lead with the workflow boundary:
Inngest owns durable steps and retries. Bilig owns formula workbook state and returns a compact patch plus readback proof from one
step.run().
Do not post it as a generic spreadsheet-engine pitch. Link the runnable example and smoke output, then ask whether a formula-backed durable step recipe would be useful to Inngest users.