The emulator family
— repositories, one registry →Clean-room emulators of the control planes nobody else emulates (Entra ID, ARM with real RBAC, Key Vault, API Management), and of the analytics engines behind a data product: Fabric, Databricks and Snowflake. Local, deterministic, free, and resettable in seconds.
So the agent builds, runs, reads the actual response and corrects itself hundreds of times before a person looks. Then the same code points at the real service by changing environment variables.
Every capability carries the test that proves it, and this page says which claims are proved by something that is not us, and which are not proved at all.
It was never that an agent cannot write the code. It is that it cannot prove it, and proving an Azure-shaped system means a tenant.
Minutes per round trip, state that does not reset, and a blast radius that makes an agent's normal behaviour, try it and look and try again, expensive and frightening. So the agent writes plausible code and a person spends weeks finding out where it was wrong.
docker compose down -v · a clean tenant in seconds, for freeIdentity, authorization, secrets and a gateway come before anything interesting. A fake token issuer teaches an agent nothing about audience mismatches, and a permissive secret store teaches it nothing about RBAC. A permissive mock actively teaches the wrong thing.
separate processes, separate ports, real tokens validated over HTTPAn agent that iterates fast against a bad emulator converges fast on the wrong answer, and produces confident code that fails on first contact with Azure. Fidelity is not a nice-to-have here; it is the entire premise.
clean-room from published specification, never decompiled product codeFour cross-cutting planes in every stack, three analytics engines beside them, and one data product definition that every cell installs by tag rather than copying.
Each emulator grades itself in a parity ledger, and every green row names the test that proves it. The figure on each card is the share of that emulator's claims proved by something that is not our own client: Microsoft's own SDK linked in process, or a packaged third-party client running in CI.
entra-emulator BOMEntra ID, the STS. MSAL-compatible OIDC and OAuth2, issuing every token the others validate. The single highest-value one to adopt alone, because identity is the first thing that blocks local development.
—arm-emulator BOMThe ARM control plane with Microsoft.Authorization role assignments, so
“no assignment means no access” is something an agent discovers rather than
something it is told. Scoped deliberately to the authorization slice, not all of ARM.
azure-keyvault-emulator BOMThe Key Vault data plane: secrets, real RSA and EC cryptography, X.509 certificates, with tokens validated against ARM's RBAC rather than accepted.
—azure-apim-emulator BOMManagement plane, gateway and policy engine. The loop against a real APIM instance is minutes per policy edit, which is exactly the cost structure that makes agent-driven policy work impractical.
—fabric-emulator BOMMicrosoft Fabric's control plane and OneLake, with a real Spark engine behind it: notebooks, Data Pipelines, a Warehouse over TDS, semantic models and Power BI over XMLA.
—databricks-emulator BOMThe Azure Databricks workspace REST surface: Jobs, the Statement Execution API, Unity Catalog, PAT and OIDC identity with entra as an optional federated issuer.
—snowflake-emulator adjacentA Snowflake account on DuckDB, with the same discipline: a graded ledger, a witness manifest, and a checker enforcing both. Deliberately outside the certified compose and the chain test, so the family subtotal does not quietly include it.
graded ledger · not in the BOM · not in the chain testazure-emulators holds the bill
of materials, the pinned docker compose, and a chain test that runs the whole
set together: — of the
— emulators above. A family of parts that each pass
alone is not the same claim.
The concrete result, and the reason any of this is worth building.
The same Contoso data product runs on Fabric, on Databricks and on Snowflake, through
— orchestration idioms, from four real source
systems through a medallion lakehouse to a semantic model. Every cell reproduces
— of revenue across
— sale lines.
Porting a data product across analytics engines is normally a project with a business case. It happened here because each attempt cost seconds instead of a tenant round trip, and because the comparison could tell an agent it was wrong without a human reading dataframes.
Until recently the nightlies proved a pipeline had run and nothing about the answer: a cell whose gold silently returned different money would have stayed green indefinitely. All — now hold their own published snapshot to figures the core repository states as data. Two of them turned out not to be writing a snapshot at all.
The discipline here is that a claim is worth what checks it. The same rule applies to this page, so the rows that are not green are on it.
| Claim | Status | What backs it, or what does not |
|---|---|---|
| Parity ledgers with enforced witnesses | shipped | — green claims across the BOM, each bound to a named test in a witness manifest; CI fails on a dangling reference |
| Proved by something that is not us | measured | —–—% per emulator, by Microsoft's own SDKs or packaged third-party clients in CI. Run family_parity.py --evidence yourself rather than trusting the snapshot |
| A pinned, chain-tested family | shipped | A BOM, a certified compose and a chain test in azure-emulators |
| One product on three engines | witnessed | — cells, same three figures to the last digit, each asserted by its own unattended nightly |
| Diffed against real Azure | not run | No emulator here has Azure differential evidence. apim is the only ledger that defines the grade and it awards it zero times. Green means witnessed locally against real clients, which is a strong claim and a different one |
| The data product against a real tenant | not run | fabric-emulator's real-Fabric conformance job exists and skips: the credentials are incomplete, so the gate reports it and the job never runs. The workflow is green with that leg untested, which is why it says so out loud |
| snowflake-emulator in the BOM | deliberately not | Same discipline and a graded ledger, but outside the certified compose and the chain test. Joining would change what the family subtotal means, which is a release-coordination decision rather than a naming one |
| Breadth of Azure services | narrow on purpose | Seven services deep, not eighteen shallow. If you want breadth-first coverage, the comparison says where the alternatives are better |
| arm-emulator's scope | scoped | It reads in the nineties on both metrics, on a ledger its own boundary scopes to the authorization slice rather than all of ARM. A near-perfect score on a deliberately narrow slice is the row most likely to be misread |
| Clean-room construction | enforced | From published specification and observed protocol behaviour. Nothing decompiled is ever committed, only protocol facts |
Not part of the family. Things built with it, each running locally against these emulators and unchanged against real Azure.
data-agent-service shippedNatural-language questions over the warehouses, databases and APIs you already have, grounded in the glossary and metrics held in OpenMetadata and fronted by API Management. Each query is authorized twice: role rules in the service, then the engine under the caller's own identity.
two executor images · every configured source · MCP, client-agnosticdata-agent-voice plan and scaffoldingThe Analyst Line: ask aloud, and hear the answer with the definition it applied. Built around a measured gap. A question upstream takes twenty-six seconds at the median and a conversation reads as broken after about one, so the conversation stops waiting for the agent.
no audio has ever been through it; its ledger says sosqlglot-go shippedA Go port of sqlglot, verified statement by statement against the Python reference. Scoped to what a read-only SQL guard needs and built outward, which is what lets the Go executor above be a static binary on distroless.
verified against the reference implementation, statement by statementGenerated from members.json, and CI fails when the picture and the
registry disagree. The shapes are the ontology, not
decoration: colour is the tier, a row is a cell, and a cell is always a leaf plus a
platform.
Three doors in, depending on whether you want the emulators, a whole data product, or one piece of either.
The emulators, on their own. The certified set, pinned together.
git clone https://github.com/calvinchengx/azure-emulators
cd azure-emulators
docker compose up # entra + keyvault + arm
docker compose --profile fabric up # ...and fabric
docker compose --profile databricks up # ...or the Databricks workspace
A whole data product, end to end. One launcher over every cell, reading the pair, the verbs and the ports from the registry.
git clone https://github.com/calvinchengx/emulators
cd emulators
./family ls # every cell, its two repos, its ports
./family up fabric-airflow3 # tells you which siblings to clone, if any
./family witness fabric-airflow3 # exit 0 only if the numbers hold
./family down fabric-airflow3
One piece. Plenty of agent work needs only identity, or only identity plus RBAC. Working à la carte says which combination answers which question, and getting started has the rest of the commands.
docker compose down -v between attempts is what stops a corrupted run from
poisoning the next twenty. And when an agent hits a wall, the first question is whether the
emulator claims that capability at all. The parity ledger answers it in one grep,
which is cheaper than the agent inventing a workaround for something deliberately absent.