A whole company to build against.
Era runs a synthetic company inside the systems your product integrates with. Each one answers like the vendor it imitates, over REST and MCP. The data is the same on every run, and you can push the whole company forward a quarter. Nobody's real records are in it, and you need an account with none of the vendors to reach it.
Integrations and agents have nowhere to run.
Code that reads a customer's CRM, files a ticket and answers questions out of chat needs somewhere to live while you write it, and something to assert against once you have. There are three usual answers, and all three cost more than they look.
A customer's real tenant
Real records, real people, and a credential that reaches them. You cannot put that in CI, you cannot demo on it, and a write that goes wrong lands on somebody's business.
✕ not safe to automateA vendor sandbox
Credentials no CI job should be holding. Data that reads differently next week. Rate limits your test matrix will trip. And no way to say: it is next quarter now, and the renewal closed.
✕ drifts under the suiteHand-written mocks
A mock answers the calls you thought of, in the shapes you thought of. And it agrees with nothing: the account in your CRM fixture appears in no ticket and on no call, so there is nothing to grade a cross-system answer against.
✕ agrees with nothingThree jobs, one company.
Integration and connector teams
You can only test a sync if you can move time. Read the estate, push it forward a quarter, read it again: the difference is what your incremental sync should have picked up. Throttling, latency, 500s and a blown quota are one admin call away on a simulator you run yourself, so the retry paths get exercised instead of assumed.
Testing & CI · day-states, faults, tenantsAgent builders and evaluators
Every system runs an MCP server next to its REST API, so an agent works this estate the way it would work a customer's. Writes are refused unless you ask for them, which is what makes an agent under test safe to run at all. A frozen company also comes with its ground truth recomputed, so you can score the answer you got.
MCP · one endpoint per systemTeams that have to show the product
Pick the industry, the size and the systems your audience actually runs, and Era stands up a company they will recognise: customers, deals and two years of history that line up instead of placeholder rows. When the call ends, throw it away.
Generate a company · in the browserDescribe a company, then point clients at it.
/mcp on the same origin, with your token as the credential in the header
that vendor reads. The console speaks MCP itself, so an agent can build the environment as well as
work in it.One command, endpoints in .env
The CLI signs in through this console, provisions the environment and writes every system's endpoint and the tenant's token where your agent already looks for them.
The same simulators, offline
Released systems are published as images, one per system, so a suite composes the estate it needs and runs with no console, no network and no credential to leak.
The company comes first. The systems are views of it.
Synthetic data is usually made one system at a time. A script fills a CRM with plausible-looking rows, another script fills a helpdesk, and neither one has heard of the other. It holds up until a test asks a question that crosses a boundary. Era works the other way round. The company is built first: its people, its customers, the deals those customers signed, the tickets they filed, the calls they sat on, and the files and chat that came out of all of it. Every system then serves a slice of that one company in its own vendor's schema.
A seed, a clock and a day-state are the whole input. Give it the same three and you get the same company back, down to the ids, so a count you assert on today is still right next month.
The requester on a Zendesk ticket is a contact at the account the Salesforce opportunity names, and the agent who answered is the employee HiBob has on that team. The ids match because there is one company underneath, not three.
Why that beats a row generator
Coherence is the obvious win. It is not the interesting one. Once the company is a graph and not a pile of tables, you can model the things that make real data awkward, and those are the things software gets wrong. About forty modules do nothing else: the working week, public holidays country by country, where people sit, job levels and job families, promotions and transfers, leave, churn and win-back, the demand funnel, on-call rotations, how free text is actually worded.
| What a test or an agent asks | Rows-in-a-table synthetic data | Here |
|---|---|---|
| Whose ticket is this? | An account id that appears nowhere else. | A contact at a customer the CRM also books, who was on the call about it. |
| When was it created? | Uniform random over the window, holidays and midnight included. | Sampled in the record's own timezone: weekday-heavy, office hours, a lunch dip, a thin evening tail, almost nothing on a public holiday. |
| Who reports to whom? | A flat list of titles, and a title is prose. | Levels and job families derived as data, so a program can tell that one title outranks another instead of matching substrings. |
| Has anything ever changed? | Everyone was hired once and never moved; every logo is still a customer. | Promotions, transfers and reorganisations behind the roster; customers that went dormant, downgraded, churned with a reason, or came back. |
| Do two products agree on a number? | Each one invented its own, so the ad clicks and the sessions in the traffic reports describe different companies. | One funnel underneath: the same demand shows up in the ad platform, the traffic reports, the search console and the CRM's leads. |
| What does the text actually say? | Lorem ipsum, or the subject line pasted into the body. | Bodies written out of the record's own entities: the account, the error code, the person who filed it. Deterministic, and no model call at build time. |
| What does next quarter look like? | Generate again with a different seed. It is a different company. | The same company, 91 days on, moved once across every system at the same time. |
There is no generic simulator. Somebody has to write each one.
The shared graph took a while. It is nothing next to the part after it, which is making each system behave the way its vendor does, closely enough that the vendor's own client runs against it with only the base URL changed. That work does not generalise. It is one product at a time, and it is most of what is in the tree: about a million and a half lines of Python behind the fleet, and another million in its tests.
Routes, query languages, pagination, errors
SOQL here, JQL there, a Postgres wire protocol somewhere else. Cursor pagination in
one product, offsets in the next, and everybody's own error envelope: a Slack ok:false,
an S3 REST-XML fault, a Salesforce error array. Get any of it wrong and the SDK you wanted to test
with throws on the first call.
One token, every vendor's idea of a header
The console mints one tenant-bound token. Then every connector has to declare how its
real client would present it, because none of them agree: CircleCI reads Circle-Token,
PagerDuty wants Authorization: Token token=…, LaunchDarkly takes a bare header, AWS
expects a SigV4 credential scope. OAuth codes, device codes and sessions are minted and recorded per
tenant too, since the login flow is part of what a client exercises.
MCP cannot be the wider door
Every system publishes MCP tools next to its REST methods, off the same token. A tool
that skipped the scope check would be a wider door than the method it mirrors: a grant the API
answers 403 to would drive the whole product through /mcp. So a tool is held to the
scope its REST equivalent needs, and the refusal comes back as a protocol error, because by then the
session is authenticated.
One quarter, agreed by everybody
Advancing a tenant used to mean every simulator inventing its own delta, and the deltas agreed about nothing. A helpdesk gained a ticket, the CRM gained an account nobody had ever met, no calendar moved at all, and the staff never changed. The quarter is computed once from the company now and handed to all of them. A sync window is only worth testing if everybody moved together.
The vendors' own test suites, pointed at us
Fidelity is easy to claim, so it gets checked with code nobody here wrote.
zenpy's Zendesk suite runs with its cassettes flipped to record mode, which puts the
requests it once recorded against a real account back on the wire. psycopg 3's own suite is written
against a server and not against the driver, so it can be pointed at the Postgres simulator. Then
stripe-python, the Jira client, elasticsearch-py, minio-py, pymysql, clickhouse-connect, and the
vitest suites from vercel-labs/emulate. Every upstream is pinned, and every connector
carries an audit file saying what was probed, what was broken, and which test pins the fix.
What a mock cannot give you.
Its vendor's own surface, not a stub
Each system serves its own product's routes, query language, pagination, credential
header and error envelope: a Slack ok:false, an S3 REST-XML fault, JQL, SOQL, a SQL
statement. Change the base URL and the vendor's own SDK talks to it, which is what the upstream
client suites are there to prove. And each one says what it is at /_meta, so a client
never has to guess.
One company, every system
The whole estate comes out of one synthetic company graph. The account in the CRM is the account the ticket and the recorded call point at, and the people in chat are the people in the HR directory. An answer that needed three systems is one you can check.
The same estate on every run
A tenant's data is a function of its seed, its clock and its day-state. Assert on a count today and it is still true tomorrow. Nothing is fetched from a vendor, so nothing drifts under the suite while you are not looking.
A quarter you can step through
Three points in the company's life, and advancing moves every system at the same time: people hired and gone, customers signed, expanded and churned, deals moved on, and a quarter's worth of tickets, files, calls and messages. The three states are a cycle, so advancing past day2 puts the tenant back to empty, and you can jump straight to the one you want.
A fleet, not one vendor with a coat of paint
It spans the SaaS and infrastructure systems this deployment serves, from CRM, support, chat and calls to file stores, clouds, databases, observability and CI.
An agent works this estate over MCP
MCP is not bolted on for a demo. Every system publishes its tools over streamable HTTP
at /mcp, a write comes back as a protocol error while the tenant is read-only, and the
console has account and provisioning tools of its own. So an agent can open an account, build its
environment and then work in it without leaving the protocol. Moving the company a quarter is the
one thing it steps out for: that is a call on the console's API.
What Era is not.
Build one and point something at it.
Era is open to builders one account at a time.