RoboLedger Demos
RoboLedger ships a suite of self-contained demos that exercise the full accounting stack — ingest, mapping, period close, reporting, and XBRL export — entirely against the local stack, with no live QuickBooks connection. They come in three flavors:
- Synthetic data (
just demo-roboledger) — a fully-populated tenant generated from synthetic books: 16 months for a consulting firm, a filed annual report, a mapped Chart of Accounts, schedules, and one period queued for the AI-driven close. The fastest way to see RoboLedger end-to-end (~60 seconds), and the canonical surface for prospect demos, frontend evaluation, and regression testing. This page walks through it in detail. - Showcase scenarios (
just demo-coffee-roaster,just demo-saas-startup) — the same scenario engine pointed at two businesses with a story: Driftline Coffee (profitable but cash-poor) and Cadence Labs (burning cash on a deferred-revenue runway). Use these when the shape of the numbers is the point. See Showcase Scenarios below. - Seattle Method / XBRL (
just demo-seattle-method,just demo-world-online) — built on Charlie Hoffman's published Seattle Method reference datasets. These prove cross-taxonomy projection and round-trip XBRL fidelity against an external reference, at both toy and realistic scale. See Seattle Method XBRL Demos below.
Connecting a real QuickBooks company (sandbox or production) is a live OAuth connection rather than a demo — see Connecting QuickBooks Locally.
The synthetic demo needs no QuickBooks account, Intuit Developer setup, or ngrok tunnel. It emulates data arriving the same way a real QB sync produces it — same typed event vocabulary, same OLTP shape, same materialized graph — without the OAuth and external-API requirements.
Table of Contents
- Overview
- Prerequisites
- Quick Start
- What Gets Created
- The Company — Cascade Advisory Group
- The Filed Annual Report
- The Close-Period Workflow
- The Rule Engine
- The Mapping View
- Schedules
- Frontend Tour
- Exploring with MCP
- Resetting the Demo
- Customization
- Comparison to the QuickBooks Workflow
- Showcase Scenarios
- Seattle Method XBRL Demos
- Next Steps
Overview
When just demo-roboledger finishes (~60 seconds), the tenant has:
- A new entity (or one provisioned into an existing graph) modeling Cascade Advisory Group LLC, a 3–5 person boutique consulting firm
- 16 months of business data on a rolling window ending at the current month, so the demo always covers "recent history" regardless of when you run it
- A clean 27-account Chart of Accounts, fully mapped to rs-gaap
- ~305 typed business events (
invoice_issued,payment_received,bill_received,bill_paid,journal_entry_recorded) emulating data arriving via the same HTTP API a real adapter uses - ~132 discharge chains linking payments to their originating invoices/bills (REA duality)
- A fiscal calendar with the prior month's prior month closed and the last completed month queued — exactly one period ready to close
- 6 schedules: 2 depreciation, 4 prepaid amortization, staggered across the window
- 4 policy documents (close procedures, depreciation, prepaid, revenue)
- An FY annual report — generated, packaged, and filed as a complete Report-Block lifecycle demonstration
After setup, the natural flow is:
- Open the frontend, browse the entity, mapping coverage, and the filed annual report
- Drop into the AI close workflow on the queued period via Claude Desktop or any MCP client
- Inspect the verification output — the rules attached to each Information Block, plus the rule tallies the close itself returns
- Query the graph directly to explore the data shape
Prerequisites
Just the local stack:
git clone https://github.com/RoboFinSystems/robosystems.git
cd robosystems
just start
You don't need Intuit credentials, ngrok, or any external service. The demo is fully self-contained and runs entirely against the local stack.
If you want to drive the AI close workflow at the end, you'll also want an MCP client (Claude Desktop, Claude Code, or a custom client). That's optional — everything else inspects via the frontend or the API.
Quick Start
# In one terminal — start the backend stack if you haven't already.
cd robosystems
just start
# In another terminal — start the frontend (optional, but recommended for the tour).
cd ../roboledger-app
npm run dev
# Run the demo. ~60 seconds.
cd ../robosystems
just demo-roboledger
Output includes the API key + user credentials and the graph id of the new tenant — copy them or read them from .local/config.json. The last line prints the exact MCP prompt to use for the AI close on the queued period.
To load the demo into an existing graph (e.g. on a user / graph you've already provisioned):
just demo-roboledger <graph_id>
To validate the data without writing anything:
just demo-roboledger --dry-run
To provision a user + empty roboledger graph without the synthetic data (for connecting a real QuickBooks sandbox via the UI — see Connecting QuickBooks Locally):
just demo-roboledger --skeleton
To swap the hardcoded CoA → GAAP mappings for AI-driven mapping via the MappingOperator (requires Bedrock):
just demo-roboledger --ai
What Gets Created
| Component | Count | Detail |
|---|---|---|
| Chart of Accounts | 27 | Clean asset / liability / equity / revenue / expense breakdown with realistic small-business categories |
| Agents | 17 | 6 customers + 8 vendors + 2 employees + 1 government (IRS). Same shape a real QB sync produces. |
| Business events | ~305 | Typed event stream: invoice/payment pairs, bill/payment pairs, opening-balance and payroll journal entries. Mirrors the exact event vocabulary QB ingestion emits. |
| Discharge chains | ~132 | payment_received → invoice_issued and bill_paid → bill_received links — the REA duality that drives open-AR / open-AP aging |
| CoA → rs-gaap mappings | 27 | 100% coverage. 24 are renderable under the active Reporting Style; 3 PP&E-gross targets are unreachable — see The Mapping View |
| Fiscal calendar | 1 | closed_through = month_before_last, close_target = last_completed_month |
| Fiscal periods | 16 | One per month, first 14 closed, last 2 open |
| Schedules | 6 | 2 depreciation (computer equipment, office furniture) + 4 prepaid amortization (business insurance, its year-two renewal, software subscription, cloud hosting) |
| Schedule facts | mixed | Historical (pre-target, baked into opening balances) vs in_scope (target onward, surfaced by the close workflow) |
| Documents | 4 | Markdown policies: close procedures, depreciation, prepaid, revenue recognition |
| Filed FY report | 1 | Annual report — facts generated, package assembled, lifecycle stamped filed. Demonstrates the full Report-Block lifecycle end-to-end. |
| Verification rules | ~134 | Not authored by the demo — auto-generated. One SumEquals proof per schedule, plus the RollUp / EqualTo / Derive rules that ship with the seeded rs-gaap statement structures. Count them yourself in The Rule Engine. |
Every event flows through the same HTTP API the frontend UI and MCP tools call. The only direct-DB path is _reset.py, used to clean up between re-runs.
The Company — Cascade Advisory Group
The demo emulates Cascade Advisory Group LLC, a 3–5 person boutique management consulting firm. Grounding the data in a believable business shape makes the close workflow, the report numbers, and the policy documents all read as coherent — closer to what a real customer would walk in with than abstract test fixtures.
| Aspect | Value |
|---|---|
| Service lines | Three revenue streams: general consulting, strategy advisory, implementation services |
| Monthly revenue | $18K – $22K, with seasonality |
| Customers | 6 named customers across professional-services verticals |
| Vendors | 8 named vendors: landlord, payroll provider, AWS, software licenses, etc. |
| Employees | 2 — driving the monthly payroll JE |
| Key expenses | Payroll ($9,500/mo), rent ($2,500/mo), software ($450/mo), cloud hosting ($180/mo), professional services |
| Fixed assets | $4,800 computer equipment + $1,500 office furniture (driving depreciation schedules) |
| Prepaids | $1,200/yr insurance + $300/yr software + $600/yr AWS prepay (driving amortization schedules) |
The 16-month rolling window means the demo is always running a business — you're never in "future data" or "ancient history." That matches how real customers experience the product.
The Filed Annual Report
The most material output: a fully-rendered FY annual report, filed, demonstrating the Report-Block lifecycle from generation through packaging through filing.
To inspect:
API_KEY=$(jq -r .api_key .local/config.json)
GRAPH_ID=$(jq -r '.graphs | keys[0]' .local/config.json)
# List reports — reads go through the graph-scoped GraphQL endpoint.
# Note the double nesting: the `reports` root field returns a ReportList,
# whose own `reports` field holds the rows.
curl -X POST "http://localhost:8000/extensions/$GRAPH_ID/graphql" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ reports { reports { id name filingStatus periodEnd } } }"}' | jq '.'
# Inspect facts on the filed report
docker exec robosystems-pg psql -U postgres -d extensions -tAc "
SET search_path TO $GRAPH_ID;
SELECT s.block_type AS statement,
REPLACE(e.qname, 'rs-gaap:', '') AS concept,
ROUND(f.value::numeric, 2) AS value
FROM facts f
JOIN fact_sets fs ON fs.id = f.fact_set_id
JOIN elements e ON e.id = f.element_id
JOIN structures s ON s.id = fs.structure_id
WHERE fs.report_id = (SELECT id FROM reports WHERE filing_status = 'filed' LIMIT 1)
ORDER BY s.block_type, ABS(f.value) DESC;"
You'll see facts distributed across all four statements (Balance Sheet, Income Statement, Cash Flow, Statement of Equity). The trial balance balances to the cent, retained earnings rolls forward correctly, and dividends/distributions net out of equity as expected.
In the frontend, navigate to Reports → the filed FY report → view the rendered BS / IS / CF / SE statements with drill-downs into Information Blocks for supporting detail.
The Close-Period Workflow
The fiscal calendar is initialized so the prior month's prior month is closed_through and the last completed month is the close target — exactly one period ready to close. This matches what a real business onboarding mid-year does: wall off pre-onboarding periods as historical, start running the close workflow from a clean boundary.
The natural way to drive the close is via the AI workflow. With Claude Desktop or any MCP client connected to the local RoboSystems MCP server:
- Paste the prompt from
examples/roboledger_demo/prompt.md(or copy the close-month-specific prompt the setup script prints at the end) - Ask: "Close the books for the most recent completed month."
Two checklists are in play, and it's worth keeping them apart.
The tenant's accounting procedure is a document loaded into the graph — search-documents for "close procedures" finds it. It is the human-readable policy for this company, and for Cascade Advisory Group it runs:
- Bank reconciliation — reconcile Operating Checking to the statement
- Accounts receivable review — invoices sent, AR aging, unbilled revenue
- Accounts payable review — vendor bills entered, payroll taxes current
- Depreciation — post the two fixed-asset schedules ($158.33/month combined)
- Prepaid expense amortization — post the active prepaid schedules
- Review trial balance — debits equal credits, compare to prior month
- Generate financial statements — income statement, balance sheet, mapping rollups
- Period close — close the fiscal period once everything is posted
The executable tool sequence is a different thing: the generic MCP workflow that actually drives the close. Don't reconstruct it from this page — ask the server. get-close-playbook returns it, version-locked to the deployed build, so it can never drift from the tool names and schemas it describes. As of the current build the recurring sequence is:
get-fiscal-calendar— orient:closed_through,close_target,closeable_now, blockerssync-connection— only if the blockers includesync_stale; then poll until it clearsget-period-close-status— which schedules are pending / drafted / posted, and for how muchpromote-obligations(dispatch_handlers=true) — drafts every matured schedule's closing entry in one sweep. This is how schedule drafts come into being; there is nocreate-closing-entrytool. Manual one-offs go throughcreate-event-blockwithevent_type='journal_entry_recorded'.list-period-drafts— review every draft with DR/CR detail and theall_balancedcheck- Summarize to the user and get explicit approval
close-period— atomic: posts the drafts, runs the balance-sheet equation check, stamps the period's statement FactSets, advancesclosed_through- Post-close verification — read the receipt back:
entries_posted,statements_stamped,rule_summary,statement_rule_summary
Note what is not in it: evaluate-rules is not a close step. The close runs the rules itself and hands the tallies back on its own response (see The Rule Engine).
Each step exercises a different RoboLedger surface: documents, schedules, journal entries, verification, period management, reports. The agent's run is auditable — every action is a typed operation in the event log, replayable on demand.
If you'd rather drive manually, the same operations are exposed via REST under /extensions/roboledger/{graph_id}/operations/.
The Rule Engine
Rules are not a global corpus you run against the tenant. Every rule hangs off an Information Block — it is part of the block's envelope, alongside the block's elements, facts, and verification results. That is the single most important thing to internalize about verification in RoboLedger, and it's why there is no "list all rules" endpoint.
The demo authors none of them. They arrive two ways:
- One
SumEqualsproof per schedule. Give a schedule a cost basis (original_amount) and the platform generates the rule that proves the periodic amounts sum back to it. All six demo schedules carry one. - The seeded rs-gaap statement structures. Balance sheet, income statement, cash flow and equity blocks arrive from the taxonomy library with their
RollUpandEqualTorules already attached — the calculation arcs, expressed as verifiable rules. TheDeriverules on those blocks (and on the metric block) are the other half of the same grammar: same$Variableexpressions, evaluated to compute a value rather than to check one, which is whatcompute-metricsruns.
To see them, walk the blocks:
curl -X POST "http://localhost:8000/extensions/$GRAPH_ID/graphql" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ informationBlocks { name blockType rules { rulePattern ruleSeverity ruleOrigin } } }"}' \
| jq '[.data.informationBlocks[].rules[]] | group_by(.rulePattern)
| map({pattern: .[0].rulePattern, count: length})'
On a freshly loaded demo tenant that returns roughly 134 rules: ~88 RollUp, ~30 Derive, ~10 EqualTo, and the 6 schedule SumEquals proofs. The exact numbers move with the seeded rs-gaap library, which is why the query above is the answer rather than a table on this page.
The pattern vocabulary is broader than what the demo happens to exercise — Adjustment, CoExists, Derive, EqualTo, Exists, GreaterThan, GreaterThanOrEqualToZero, LessThan, RollForward, RollUp, SumEquals, Variance. Of those, EqualTo / RollForward, RollUp, Exists, CoExists, and SumEquals have evaluators today; the rest return skipped rather than failing.
Evaluating a block
evaluate-rules is scoped to one Information Block. It takes a structure_id — posting an empty body returns a 422:
# Pick a block — here, the first of the six schedules
BLOCK_ID=$(curl -s -X POST "http://localhost:8000/extensions/$GRAPH_ID/graphql" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ informationBlocks(blockType: \"schedule\") { id name } }"}' \
| jq -r '.data.informationBlocks[0].id')
curl -X POST "http://localhost:8000/extensions/roboledger/$GRAPH_ID/operations/evaluate-rules" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"structure_id\": \"$BLOCK_ID\"}" | jq '.result.summary'
The response is an OperationEnvelope whose result is {structure_id, results[], summary}. summary is a count keyed by outcome — {"pass": N, "fail": N, "error": N, "skipped": N} — and results carries one row per rule. Optional period_start / period_end narrow the fact-binding window; without them the engine binds the most recent in-scope fact per element.
What the close runs for you
You rarely call evaluate-rules by hand during a close. close-period runs the engine itself — over every schedule structure with facts in the closed period, and over the statement blocks it just stamped — and returns the tallies on its own response:
rule_summary— the schedule-rule tally (pass/fail/error/skipped), withevaluated_structure_idsnaming the blocksstatement_rule_summary— the same tally across the stamped canonical statements
That is the verification surface an operator actually reads: the close reports what passed, not a separate validation pass run beforehand. The demo data is intentionally clean, so the value here is seeing the shape of the output — once the agent starts proposing adjustments, these are the numbers that catch anything that would break the books.
The Mapping View
All 27 CoA accounts are mapped to rs-gaap reporting concepts. Coverage and renderability are two different measurements, and the demo is deliberately set up to show the gap: 27 of 27 are mapped, 24 are renderable, and 3 target concepts the active Reporting Style's structures don't walk.
From the frontend, Chart of Accounts shows each account with its rs-gaap target alongside. From the MCP:
list-mapping-structures
→ returns the CoA→rs-gaap mapping structure id
get-mapping-summary --mapping_id=<id>
→ {
"mapping_id": "struct_…",
"total_coa_elements": 27,
"mapped_count": 27,
"unmapped_count": 0,
"coverage_percent": 100.0,
"confidence_distribution": { "high": 27, "medium": 0, "low": 0, "manual": 0 },
"unreachable_count": 3,
"unreachable": [
{ "coa_code": "1300", "coa_name": "Computer Equipment",
"target_qname": "rs-gaap:PropertyPlantAndEquipmentGross" },
{ "coa_code": "1310", "coa_name": "Office Furniture",
"target_qname": "rs-gaap:PropertyPlantAndEquipmentGross" },
{ "coa_code": "1350", "coa_name": "Accumulated Depreciation",
"target_qname": "rs-gaap:AccumulatedDepreciationDepletionAndAmortizationPropertyPlantAndEquipment" }
]
}
The three unreachable mappings are the PP&E-gross pair and its contra — correct mappings at a grain the active Reporting Style presents net, so they never surface as their own statement lines. That's a real modelling situation, not a defect, and it's exactly the case unreachable_count exists to make visible.
By default the mappings come from the hardcoded table in examples/roboledger_demo/mappings.py. Pass --ai to have the MappingOperator generate them instead (requires Bedrock). The 27 accounts are chosen to have unambiguous canonical targets (Operating Cash → CashCashEquivalentsAndShortTermInvestments, Consulting Revenue → RevenueFromContractWithCustomerExcludingAssessedTax, etc.) — useful for showing how the workflow looks when coverage is complete, separately from the harder real-world mapping cases.
Schedules
The demo creates 6 schedules to show RoboLedger's recurring-entry surface:
| Schedule | Type | Basis | Monthly amount |
|---|---|---|---|
| Computer Equipment Depreciation | Depreciation | $4,800 PP&E, 36-month life | $133.33 |
| Office Furniture Depreciation | Depreciation | $1,500 PP&E, 60-month life | $25.00 |
| Business Insurance | Prepaid amortization | $1,200 annual policy, 12 months | $100.00 |
| Business Insurance (Year 2 Renewal) | Prepaid amortization | $1,200 renewal, 12 months, starts after year one runs out | $100.00 |
| Software Subscription | Prepaid amortization | $300 annual license, 12 months | $25.00 |
| Cloud Hosting (AWS Savings Plan) | Prepaid amortization | $600 annual commitment, 12 months | $50.00 |
The start offsets and useful lives are staggered on purpose, so the set covers every case: schedules that straddle the closed_through boundary, a year-one policy that has already run out before it, and the year-two renewal that starts after it. That mix is what makes the first close draw only the months a real bookkeeper would still owe.
Schedules generate schedule facts for each period in their window. Facts before closed_through are flagged historical (already baked into the closed-period opening balances). Facts at or after the close target are flagged in_scope — they're the obligations the close workflow proposes to materialize as actual entries.
A schedule is an Information Block with blockType: "schedule", so you inspect it the same way you inspect any other block:
curl -X POST "http://localhost:8000/extensions/$GRAPH_ID/graphql" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ informationBlocks(blockType: \"schedule\") { id name blockType } }"}' | jq '.'
For the mechanics behind a single schedule — the debit/credit template, the cost basis, the generated periods — call the get-information-block MCP tool with the block's id.
Frontend Tour
Once the demo is loaded, walk through these screens in roboledger-app at http://localhost:3001:
| Screen | What to look at |
|---|---|
| Home | The landing dashboard for the tenant |
| Entity → Entity Info | The Cascade Advisory Group profile, with fiscal year metadata and a recent activity summary |
| Entity → All Entities | Every entity on the graph — one, for this demo |
| Entity → Connections | Empty for the synthetic demo (no QB connection — this is the whole point) |
| Agents | The 17 parties: customers, vendors, employees, IRS |
| Ledger → Chart of Accounts | 27 accounts, each with its rs-gaap mapping displayed inline |
| Ledger → Inbox | Empty for the demo (events auto-commit for QB-style sources; demo events do the same) |
| Ledger → Transactions | The full posted event log — invoices, payments, bills, payroll JEs |
| Ledger → Trial Balance | Debits and credits by account; balances to the cent |
| Ledger → Statements | Live statements rendered from the current ledger, without waiting on a report |
| Ledger → Closing Book | The fiscal calendar view + the one queued period ready to close + blocker payload (in_scope schedule facts) |
| Reports → View Reports | The filed FY annual report — click in for the full BS / IS / CF / SE rendering with Information Block drill-downs |
| Reports → Create Report | The report-authoring path that produced it |
| Reports → Publish Lists / Blocked Senders | Distribution controls for a filed report |
| Explorer | Ad-hoc traversal of the materialized graph |
| Plan | The FP&A surface — forecast blocks and scenarios over the same ledger |
| Library | The taxonomy library behind the mappings |
| Console | Direct query access from inside the app |
| Search | Full-text search across the graph, including the 4 policy documents |
The Closing Book screen is the most product-distinctive surface — it drives the AI-assisted close workflow and surfaces all the period's outstanding items in one place.
Exploring with MCP
For agent-driven exploration, the demo is the easiest entrypoint to the RoboLedger MCP server. MCP is graph-scoped — the connector URL carries the graph_id, so point your client at http://localhost:8000/v1/graphs/$GRAPH_ID/mcp with an X-API-Key header. For Claude Code:
claude mcp add --transport http robosystems-roboledger \
http://localhost:8000/v1/graphs/<your-graph-id>/mcp \
--header "X-API-Key: <your key>"
See AI Operators & MCP for the header-less connector form and the stdio bridge. Once connected, try:
"What entities are in this graph?"
→ get-graph-info
"Show me the chart of accounts grouped by classification"
→ read-graph-cypher with a MATCH (e:Element) ... query
"How many transactions per year?"
→ read-graph-cypher with a date_part('year', t.date) aggregation
"What's the close status for the target period?"
→ get-period-close-status
"Search for the depreciation policy"
→ search-documents with "depreciation"
"Build a fact grid showing year-over-year revenue"
→ build-fact-grid
"Close the books for the most recent completed month"
→ multi-step workflow: get-close-playbook, get-fiscal-calendar,
get-period-close-status, promote-obligations, list-period-drafts,
close-period
get-close-playbook is the one to start with — it returns the canonical sequence, the decisions the operator has to make, and the gotchas that aren't visible from any single tool's schema, all version-locked to the deployed build.
The full prompt for the AI close workflow lives at examples/roboledger_demo/prompt.md — paste it into the client to load the workflow context, then ask the close question.
Resetting the Demo
To re-run cleanly:
# Re-run — the demo is idempotent and always wipes prior state on the tenant before loading
just demo-roboledger
# Or fully reset everything (drops local data + auth)
just reset-local
just demo-roboledger always runs the demo's _reset.py first to clear prior events, transactions, line items, mappings, schedules, documents, fiscal calendar, and reports from the tenant, then re-loads the full data set. Useful for getting back to a known-good state after experimenting with the close workflow or breaking something with manual entries.
reset-local is heavier — drops the entire local stack's data including all users, graphs, and credentials. Use when you want a fresh slate.
Customization
The demo's content lives in examples/roboledger_demo/:
data.py— event generators (the 305 transactions). Modify to change the business shape, transaction patterns, monthly volumes, or vendor / customer lists.mappings.py— the CoA → rs-gaap mapping table. Change targets to demo different statement compositions.policies.py— the four policy documents loaded as searchable content.agents.py— the 17 parties (customers, vendors, employees, government).validate.py— a self-check run right after the schedules are created, proving the Information Block machinery holds together (FactSets exist, the auto-generatedSumEqualsrules evaluate clean, the GraphQL envelope resolves, an asset disposal computes the right NBV). Everything it creates is throwaway and removed before it returns. It also runs standalone:uv run python -m examples.roboledger_demo.validate <graph_id>.download_bundles.py— renders the exported artifact set for the filed report.main.py— the orchestration script, and whereCOMPANY_NAMEand the schedule definitions live. Idempotent (unconditionally clears prior tenant state before loading); re-running picks up your edits.
Common customizations:
- Change the company name and shape — edit
COMPANY_NAMEinmain.pyand the revenue / expense generators indata.py - Make a rule fail — schedules generate their
SumEqualsproof fromoriginal_amount; change a schedule's basis inmain.pyso the periodic amounts no longer sum back to it, then runevaluate-ruleson that block to see it caught - Demo a different industry — replace the consulting revenue generators with retail, SaaS, or manufacturing patterns
- Test multi-year history — extend the rolling window beyond 16 months in
data.py
Comparison to the QuickBooks Workflow
| Aspect | Synthetic Demo | QuickBooks Local |
|---|---|---|
| Setup time | One command (~60 sec) | 5–15 minutes (Intuit + ngrok config) |
| External dependencies | None | Intuit Developer + ngrok + QBO subscription |
| Data shape | Designed for the product — clean, 100% mappable, balanced | Real-world messy — partial mapping coverage, edge-case transaction types |
| Use for | Product evaluation, regression testing, agent demos, learning the feature set | Real-data smoke testing, your own books, adapter debugging |
| Iteration speed | Fast — re-running the recipe wipes and reloads | Slow — re-sync takes minutes, data isn't deterministic |
| Mapping coverage | 100% mapped on first run (3 targets unreachable under the active Reporting Style) | Variable — the MappingOperator runs, partial coverage typical, manual remap for edge cases |
Both paths produce the same OLTP shape, the same materialized graph, and the same Report-Block lifecycle. The demo is for showing the product; QB is for using it on your own books. See the Connecting QuickBooks Locally guide for the QB workflow.
Showcase Scenarios
Cascade Advisory Group is deliberately unremarkable — a healthy consulting firm whose books balance and whose story is "here is the product." Two sibling demos run the same scenario engine against businesses that have a financial story, for when the numbers themselves are the point:
# Driftline Coffee — a roaster that is profitable on paper and short of cash
just demo-coffee-roaster
# Cadence Labs — a SaaS company burning cash against a deferred-revenue runway
just demo-saas-startup
Both take the same flags as just demo-roboledger: an optional [graph_id] to load into an existing graph, --ai to map the Chart of Accounts with the MappingOperator instead of the hardcoded table, and --dry-run to validate without writing.
There is also a RoboInvestor demo — Meridian Ventures Fund I, including the cross-graph report share between a fund and an issuer:
just demo-roboinvestor
See RoboInvestor Operations for what it exercises.
Seattle Method XBRL Demos
Beyond the synthetic demo, RoboLedger ships two demos built on Charlie Hoffman's published Seattle Method reference datasets. Where the synthetic demo shows the product surface, these prove cross-taxonomy projection and round-trip XBRL fidelity: RoboLedger ingests an external XBRL reporting taxonomy and a ledger tagged against it, decomposes each balance's period change via rollforward Information Blocks, renders the result in both the source vocabulary and our canonical rs-gaap, exports an XBRL 2.1 + JSON-LD bundle, and reconciles the output against Charlie's published reference.
Both exercise the three-block architecture end to end — the Taxonomy Block (load the external taxonomy as a Chart of Accounts), the Event Block (ingest the tagged journal entries), and the Information Block (author the rollforwards and render the statements). See Information Blocks, Taxonomy & Frameworks, and Event-Driven Ledger.
Lemonade Stand (Test Case 1)
Charlie's 14-journal-entry Q1 2024 lemonade-stand dataset, tagged against his mini reporting framework — the smallest end-to-end proof of the methodology.
# Provision → load mini taxonomy → seed mini→rs-gaap mappings → ingest 14 JEs →
# author rollforwards → reconcile → materialize the 4-statement report.
just demo-seattle-method
# A single step. Steps: pull | provision | load | seed-mappings | ingest |
# author-rollforwards | reconcile | create-report | download-bundles.
# Only `pull` and `provision` run standalone; every other step needs --graph.
just demo-seattle-method --step provision
just demo-seattle-method --step ingest --graph <graph_id>
# Re-render just the artifacts against an existing graph
just demo-seattle-method-reconcile <graph_id>
just demo-seattle-method-create-report <graph_id>
It produces 239 mini concepts loaded as Elements, ~36 mini → rs-gaap mapping Associations, 14 Events/Entries (~32 LineItems) each carrying its business-event flow tag, and 8 rollforward Information Blocks (one per balance-sheet leaf with activity). The run then renders a line-by-line reconciliation against Charlie's published facts, the rs-gaap 4-statement Report (BS / IS / CF / SE), and a JSON-LD + XBRL 2.1 bundle — validated on the host with Arelle (XBRL 2.1 structural parity) and pySHACL (against frameworks/ontology/v1/shapes.ttl for semantic parity).
The World Online (at scale)
The scaled-up sibling — Charlie's The World Online dataset: 22,288 GL lines across 3,389 journal entries, a real 239-account chart of accounts, and opening balances, tagged against the MINI 2026 framework. Same methodology, realistic mid-size-company scale.
# Full pipeline. The 3,389-entry ingest is the intended per-entry path and takes a
# few minutes, with a live progress readout.
just demo-world-online
# Smoke-test the whole pipeline on a 50-entry subset first
just demo-world-online --limit 50
# A single step. Same registry as the lemonade stand plus trial-balance and
# statement-reconcile; again, only `pull` and `provision` run without --graph.
just demo-world-online --step ingest --graph <graph_id>
# Re-render individual artifacts against an existing graph
just demo-world-online-reconcile <graph_id> # GL pivot vs the published summary
just demo-world-online-create-report <graph_id> # rs-gaap 4-statement report
just demo-world-online-trial-balance <graph_id> # trial balance (debits = credits)
just demo-world-online-statement-reconcile <graph_id> # statement anchor totals vs the reference instance
Beyond the lemonade stand it adds a real chart of accounts collapsed to mini line items (the GL account and provenance preserved on each LineItem's metadata), a trial balance rendered via the trialBalance GraphQL query, and two reconciliations — a cell-by-cell (line-item × business-event) pivot against the published transaction summary, and a statement-level reconciliation of the four-statement anchor totals against the reference instance.
Its load-bearing design decision is opening balances as ordinary transactions: the 12/31/2023 beginning-balance lines flow through Transaction → Entry → LineItem like any other entry, tagged with an OpeningBalance flow concept, so the rollforward engine attributes them as the genesis event rather than synthesizing an opening number outside the pipeline.
Both demos classify every reconciliation delta by owner — matching, methodology gap, our bug, or source-data quality — so a report with mixed categories is more informative than an all-green one: it makes explicit what each side owns.
Next Steps
Once you're comfortable with the demo:
- Connect a real QB company — see Connecting QuickBooks Locally to layer real data on top of the same workflow
- Customize the demo — modify
data.pyto demo a different vertical for a specific prospect, or start from one of the showcase scenarios - Author your own Information Blocks —
create-information-blockbuildsscheduleandrollforwardblocks, each carrying its own verification rules - Build a custom MCP workflow — the close prompt at
examples/roboledger_demo/prompt.mdis one starting point; you can build vertical-specific agent workflows on the same MCP surface - Go deeper on the model — RoboLedger Operations (command writes and the fact grid), Reporting & Rendering (how statements are built), and Information Blocks (the unifying envelope)
If you're evaluating RoboLedger for a real engagement: run the demo, drive the AI close, read the rule tallies the close hands back, then connect one of your own QB companies via the QB Local guide. The full evaluation arc takes ~30 minutes if everything's smooth.