AI for ESG & Sustainability Reporting
Capable · M21 · lesson 21 of 24 · queued
Preview — browse every lesson free. Enroll to mark lessons complete, open partner links and save your progress. Login & enroll →
Structured Output for Reporting and Audit Systems
📖
now learning

Structured Output for Reporting and Audit Systems

15 min

It is March, two weeks into the assurance engagement. The assurer picks one line out of the company's Scope 3 inventory, a freight figure of 412 tonnes of CO2e, and asks the question every assurer asks: show me how you got this number. The carbon accountant pulls up the AI-assisted record that produced it. There is the value. There is the unit. And then nothing. No field for where the activity data came from, no field saying whether it was supplier-reported or estimated, no field naming the emission factor's database or year, no field for the method. The number is real, the work behind it was real, but the record cannot prove any of it. The accountant spends the next three days rebuilding by hand a provenance trail that should have been captured the moment the figure was created. This lesson is about designing the record so that day never comes: structured output that carries everything the reporting platform and the assurer both need, built to survive the engagement rather than to read nicely.

The Record Has Two Readers, and Both Are Machines for Trust

When AI helps produce a sustainability figure, that figure has to satisfy two audiences who never read prose the way a person does. The first is the reporting platform, the system that ingests the data and maps each figure to a specific disclosure field, an ESRS datapoint or an ISSB metric. The second is the external assurer, who samples individual figures and tests whether each traces to evidence. These two readers want the same thing in the same form: a record whose every important attribute lives in its own labelled field, so the platform can map it and the assurer can interrogate it. A figure expressed as a sentence fails both. The platform cannot map a number buried in a clause, and the assurer cannot reconstruct a number whose source is a memory rather than a field.

This is why structured output is not a presentation choice. It is the mechanism by which the rigour you build upstream survives downstream. You can look up an emission factor with perfect provenance, but if the provenance does not travel as a field on the record, it is gone the moment the figure leaves your working file. You can know in your own head that a freight figure is an estimate, but if that knowledge is not a tag, the assurer sees a number identical to a measured one. The structured record is the container that keeps source, method, and data type physically attached to the value all the way into the platform and the assurance file. The whole point of this lesson is to design that container so well that an assurer's "show me how you got this" is answered by the record itself, not by three days of reconstruction.

A figure that cannot prove where it came from is not a disclosure, it is an assertion. The record is where the proof lives, and a field is the only place an assurer can read it.

The Fields That Survive the Engagement

A record built for both the platform and the assurer has a predictable set of fields, each carrying one load-bearing piece of the proof. You will not populate every field on every datapoint, but this is the core schema for an emissions-related figure, and each field exists because an assurer asks about exactly that thing.

Value. The number alone, with no unit and no commentary fused into it. The value field holds 412, not "412 tonnes (estimated from spend)."

Unit. The unit as its own explicit field: tCO2e, kgCO2e, kWh, tonne-km, litres. A value without an explicit unit is ambiguous, and unit-mix errors hide in that ambiguity.

Source reference. The provenance of the activity data, structured: the file identifier, the page, and the line or field reference, so anyone can reopen the origin and confirm the figure. "supplier_freight_return_Q3.xlsx, sheet Road, row 14" is a source reference; "from the supplier" is not.

Primary or secondary. A tag declaring whether the figure rests on measurement (primary, supplier-reported or metered) or on estimation (secondary, averaged or modelled). This is the single most consequential non-numeric field, because it tells the assurer which figures stand on direct evidence and which on inference, and it must never be blank or inferred.

Period. The reporting period the figure covers, with explicit start and end. A period field is what catches the figure that secretly spans fourteen months or the prior-year number that wandered into the current inventory.

Factor provenance. For any figure derived from an emission factor, the factor's own lineage as structured fields: the named database, the table, the version, and the year. This is the field that stops a hallucinated factor from hiding inside a result, because a factor with no named database and year is a factor an assurer will reject on sight.

Method. How the figure was produced: metered, supplier-reported, spend-based, average-data, distance-based. Method is a disclosure in its own right, not a footnote, because the assurer judges a figure partly by whether the method is appropriate for its Scope 3 category, and because method choice is exactly what a reasonable-assurance engagement probes.

Supporting fields earn their place by the same test: anything an assurer might ask about should be a field they can read rather than a question they must ask. Uncertainty for an estimate, the responsible facility or entity, the scope and category, and a status or sign-off marker all qualify. The discipline is simple to state and powerful in effect: for every question the engagement will pose, there is a field that already answers it.

Notice how this set maps directly onto the disciplines of the rest of the chapter, which is not a coincidence: the fields are simply where each earlier discipline comes to rest. The source reference is where traced extraction lands. The primary-or-secondary tag is where the measured-versus-estimated distinction lands. The factor provenance field is where the no-factor-without-a-source rule lands. The period field is where the scope-of-time discipline lands, the thing that catches a fourteen-month invoice. The method field is where the spend-based-versus-activity-based choice lands. The structured record is not a new requirement layered on top of the chapter; it is the chapter's requirements made permanent. Each thing you were careful about upstream needs a field to live in downstream, or that care does not survive the journey. Designing the schema is therefore mostly an act of asking, for each discipline you practised, which field carries this forward, and ensuring none of them has nowhere to go.

Why Factor Provenance and Method Are Their Own Fields

It is tempting to fold the factor's database and the calculation method into a free-text note, because they feel like explanation rather than data. Resist it. The hallucinated emission factor, a plausible-looking number with no real source, is the failure mode that silently corrupts an entire footprint, and the only structural defense is a record that demands the factor's database, version, and year as fields that cannot be left empty without the gap being visible. If factor provenance is a sentence, a missing source looks like a slightly shorter sentence; if it is four required fields, a missing source looks like four empty cells screaming for attention. The same logic applies to method: when method is a tag, an assurer can filter every spend-based figure in Scope 3 and test whether spend-based was defensible there. When method is prose, that query is impossible, and the assurer has to read every record to find the ones that worry them. Fields make the dangerous things queryable; prose makes them hidden.

Asking the Model to Emit the Schema

You do not write the records by hand and you do not need to be a programmer. Your job is to define the schema, instruct the model to emit exactly that schema, and read the result to confirm the fields are populated honestly. The two formats you will ask for are JSON and CSV. CSV is a table, one row per datapoint, one column per field, ideal for figures that flow into a spreadsheet or a platform import. JSON is a nested structure, better when a record bundles sub-records, such as an emissions result that carries its activity value, its factor, and the factor's own provenance together. The model produces both reliably precisely because they are rigid and unambiguous.

A handful of disciplines make the output trustworthy rather than merely tidy.

Name every field explicitly. Do not ask for "the data structured." Give the model the field list, value, unit, source_reference, primary_or_secondary, period_start, period_end, factor_provenance, method, and tell it to populate each. A named schema is what maps cleanly into the platform and what the assurer can read without translation.

Forbid prose inside data fields. The value field holds a number, the unit field holds a unit, the method field holds a method tag, and any explanation lives in its own note field or not at all. A model left to help will happily merge "412 (spend-based estimate)" into the value field, destroying both the number and the method tag in one stroke.

Make missing fields explicit, never invented. If the factor's database is unknown, the factor_provenance field reads "missing" and the record is flagged, never filled with a plausible-sounding citation. A model that completes an empty source field with an invented database has reintroduced the fabrication problem at the formatting stage, which is the most insidious place for it to hide because the record now looks complete.

One datapoint per record. Resist letting the model collapse a quarter of freight legs into one summarised line. Each figure is its own record with its own source and method, because the assurer samples individual datapoints, not summaries, and a summary cannot be traced to a single piece of evidence.

Validate against the schema before you trust it. Structured does not mean correct. A record can be flawlessly formatted and still carry a fabricated factor provenance or a mislabelled estimate. The format makes the checks faster, it does not perform them. You still quote-the-source against the source_reference, recompute against value and factor, and confirm the primary-or-secondary tag, now against tidy fields instead of buried prose.

A Worked Example: One Freight Figure, Two Fates

Watch the 412-tonne freight figure take two paths.

The prose path. The model returns: "Outbound road freight for Q3 came to about 412 tonnes of CO2e, based on the carrier's distance data and a standard freight factor." Read by a human it sounds responsible. As an audit artifact it is nearly useless. The value is fused to its unit and its rationale. "About" hides whether this is measured or estimated. "The carrier's distance data" names no file, page, or row. "A standard freight factor" names no database, no version, no year, which means a hallucinated factor could be hiding inside that phrase and nobody could tell. The method is implied, not stated. When the assurer asks "show me how you got this," the accountant has to reconstruct every one of those facts from memory and scattered files. That is the three lost days.

The structured path. The same information, requested as a schema, comes back as one emissions record that points to its inputs. The result record: value 412, unit tCO2e, method "distance-based", primary_or_secondary "secondary", period_start 2026-07-01, period_end 2026-09-30, scope "3", category "4 upstream transportation". The activity input it references: value 1,030,000, unit tonne-km, source_reference "carrier_freight_Q3.csv, row 14, lane DE-FR", primary_or_secondary "primary", method "carrier-reported distances". The factor it references: value 0.0004, unit "tCO2e per tonne-km", factor_provenance "GLEC Framework freight factors 2026, road table, version 3, row HGV-FR", primary_or_secondary "secondary". Now the assurer's "show me how you got this" is answered by the record. The result traces to the factor, the factor names its database and version and year, the activity value traces to a named row in a named file, the method is explicit, and the primary-or-secondary tags say precisely which links rest on measurement and which on estimation. There is nothing to reconstruct. The three days do not happen, because the record was built to survive the engagement the moment it was created.

The information content barely differs between the two versions. What differs is that the second one survives the day the assurer pulls the thread, and the first one collapses into three days of rebuilding. The structured record is not a nicer way to present the work; it is the difference between a figure that can defend itself and one that needs you in the room to defend it.

It is worth noticing exactly what the structured version made possible that the prose version did not, because it is more than tidiness. The platform imports the records without a human re-keying a single number, which removes both a delay and a fresh chance to mistype. The assurer issues a query, "show me every primary activity value in Scope 2," and this freight result and its inputs surface or do not on the strength of their tags, with no reading of paragraphs required. The factor's vintage is a field, so when the grid factor is reissued next year the team can find and update every figure that used the old version rather than hunting through sentences. And the calculation reconstructs in both directions: from the published result down to the line on the carrier's file, or from a raw activity row up to the disclosed total. None of those operations is available on the paragraph, because each of them is a machine acting on fields, and a paragraph has no fields for the machine to act on. The structured record did not merely read better; it re-enabled every downstream capability the prose had quietly switched off.

Design for the Engagement, Not for the Eye

The deepest mistake in structured output is designing the record to look complete rather than to be reconstructable. A clean CSV with neat columns is seductive: it looks authoritative, it looks finished, it looks trustworthy simply by being orderly. But order is not proof. A model can produce a beautifully structured record whose factor_provenance names a database table that does not exist, whose primary-or-secondary tag is wrong, or whose value is a misread. The structure has made the record easy to read and easy to import; it has done nothing to make it true. The right posture is that structured output is a precondition for verification, not a substitute for it, and the schema's real job is to make the figure answerable to the engagement's hardest question.

So design backwards from that question. The assurer will ask, of any sampled figure: where did the activity data come from, is it measured or estimated, what factor did you apply, where is that factor published, what method did you use, and what period does it cover. A record that has a field for each of those answers survives the engagement; a record missing any of them turns that question into reconstruction work, and reconstruction is both slow and weaker, because a provenance rebuilt after the fact is a provenance an assurer trusts less. Build the schema so that every question the engagement will pose already has its answer sitting in a field, captured at the moment the figure was created, when the evidence was in front of you, rather than recovered months later when it has scattered. That is what survives the engagement means: the record was complete before anyone asked.

You Own the Schema, Not the Code

A disclosure professional reading this may feel the formats are a step too far into engineering, and it is worth dismantling that worry directly, because the skill being asked of you is not technical. You will never author the JSON or the CSV by hand. The model produces the structure; that is the one part of this that is genuinely mechanical and genuinely the machine's job. Your job is the part that requires judgment and that no model can do for you: deciding what the fields should be, insisting the model produce exactly those fields, and reading the result to confirm the fields are populated honestly. Reading a CSV is reading a table, which every reporting professional does all day. Reading a JSON record is reading a labelled list of field-and-value pairs, which is no harder than reading a form. The competence at stake is the disclosure competence of knowing that a freight figure needs a source reference, a method, and a primary-or-secondary tag, and then checking that it has them. That is your expertise expressed as a schema, not a new programming skill.

This division of labour also clarifies who owns what when something goes wrong. If the format is malformed, that is the model's failure and it is rare, because the formats are rigid. If the schema is missing a field the assurer needed, that is a design failure and it is yours, because you defined the schema. If a field is populated with a fabricated source, that is a content failure, and catching it is yours too, through verification. Keeping these straight matters, because it stops the schema from becoming a black box you defer to. The structured record is a tool you direct, not a system you trust blindly. You decide what it must carry, the model fills the carrier, and you confirm the cargo is real. Owning the schema in this way is also what lets you hand the assurer a coherent account of how AI output became disclosure data: here is the schema we required, here is why each field exists, here is the verification that confirmed each one. That account is far stronger coming from a professional who designed the record deliberately than from one who accepted whatever shape the tool happened to emit.

Key Takeaways

  • An AI-produced figure has two readers, the reporting platform and the external assurer, and both need every important attribute in its own labelled field, because neither can read a number buried in prose.
  • Structured output is the container that keeps source, method, and data type physically attached to the value all the way into the platform and the assurance file; lineage that is not in a field is lineage that does not exist.
  • The core schema for an emissions figure is value, unit, source reference, primary or secondary, period, factor provenance, and method, with each field present because an assurer asks about exactly that thing.
  • Factor provenance and method must be their own fields, not free text, because that is the only structural defense against a hallucinated factor hiding in a sentence and the only way to query every spend-based figure for review.
  • You define the schema and instruct the model to emit JSON or CSV; you do not write records by hand, but you name every field, forbid prose in data fields, mark missing fields as missing rather than invented, keep one datapoint per record, and validate against the schema.
  • Structured does not mean correct: a flawlessly formatted record can still carry a fabricated factor provenance or a mislabelled estimate, so the checks from earlier lessons still run, now against tidy fields.
  • Design the record backwards from the assurer's question, show me how you got this, so every answer the engagement will demand already sits in a field captured at the moment the figure was created.
  • The payoff is that "show me how you got this number" is answered by the record itself, turning three days of after-the-fact reconstruction into a query that the schema already satisfies.