01 · What it does
It decides who may read which data, and holds AI agents to the same rules
Munitas keeps an organisation's datasets and decides, for every request to read one, whether it is allowed. A dataset is a named collection of records, such as a table of patient admissions. It is kept as numbered versions, and a version that is sealed (finished and closed for good) can never be edited. Each dataset belongs to one department, the team that owns it, and has a sensitivity level that says how restricted it is. A person who needs a restricted dataset asks for it and says what the work is for. An approver of the owning department, called a data custodian, accepts or refuses. An accepted request gives access for that purpose and for a limited time, and every decision is recorded with its reason. The result is the kind of proof a title document gives for a property: what is held, by whom, and on what terms.
The same rules cover AI agents. Most data platforms carefully track datasets and stop there, while the AI agents that read those datasets are treated as ordinary software: deployed, changed and rerun with no permanent record of which version did what. In Munitas an agent is registered and given sealed, numbered versions, exactly like a dataset. When it runs, it gets an identity assigned by the system it runs inside, not by anything the AI model can read or write, so a malicious instruction hidden in a document cannot change what the agent is permitted to do.
Two worked example agents ship with the platform. The triage agent ranks the queue of transcripts waiting for a human to check, so reviewers start with the riskiest rather than the first in the list. The note drafter drafts a visit note from each consultation transcript, for a clinician to read, correct and sign. Section 6 describes the triage job in full, including how it has to ask a custodian for access before it can read that queue at all.
Everything below is built and running today. In detail, the platform can:
Data
- Seal a dataset version so nobody can alter it afterwards. The database itself blocks the change, so a bug in the application cannot bypass it.
- Make data available to a wider audience without copying or moving any files. Changing who may read a version only changes which access credential unlocks it.
- Make a new dataset from a query over an existing one. The new dataset is kept as restricted as its source, and withdrawing access to the source closes it too.
- Erase a person's records permanently without rewriting any sealed dataset, by destroying the key the records depend on.
- Lock the columns of a table that identify a person, so the values stay unreadable until an approver of the owning department decides a specific request to read a few rows. A privacy auditor can see how the locked columns were used in a report that contains no names.
- Lock files as they arrive, each under a key made for one person, so that one person's files can be erased later without touching anyone else's. A mistake in the list of people is caught before anything is sent.
Access
- Require a real sign-in through Ory Kratos before anyone can act, rather than letting the console take someone's word for who they are.
- Record every decision to allow or refuse access, along with the reason, so the history can be read back later.
- Let an organisation set limits on what people may ask for, such as how many rows, for how many days, how many files and hours, and how much may be brought in as tables, each inside a maximum the platform sets.
- Change who holds which role only through two people: one asks and says why, another decides, and the role lapses rather than lasting because nobody looked. The administrator who runs the platform is not one of the people who may decide.
- Let a department have several approvers, any one of whom may decide, with every change to the list recorded alongside who made it and why.
De-identification and pipelines
- Run a six-step pipeline that strips personal information out of audio recordings, then put the result in front of a named reviewer, with every identifier it measured as still left behind, before anything is released more widely.
- Judge a release by a standard the organisation wrote: a named, versioned set of limits for one audience, chosen by the reviewer, worked out again at the moment of the decision, and kept with the decision together with its version.
- Keep a pipeline version that is still being built away from real data. It may run only on a development sample that the platform draws, after an approver of the owning department has chosen how much to allow, or on files declared to hold no real person. A sample ends on its own.
- Let an organisation's own code run as one step of a pipeline, reading files and writing files, but only after an approver of the owning department who did not upload it has approved it. The step runs in a container with no route to the internet, and what it writes is sealed as a new version that waits for a review.
AI agents
- Pause an agent partway through a run and hold it there until a person approves it. The pause survives a restart, so approval can come days later.
- Hold AI agents to written risk levels. An AI risk owner writes the levels, and once an organisation switches this on, an agent needs a level the risk owner has confirmed before it can start a run. A named sponsor confirms each agent again on the schedule its level sets.
- Hold back a new version of an agent that would let it do more: a new tool, a new outside host, a copy of the data or a different model. A version that adds only tools on an approved list is approved in advance, and a first version is always decided by people.
- Have what an agent drafts reviewed by someone other than the person who started the run, suspend an agent, and bring what the platform holds about it into an evidence pack for an auditor: identifiers, counts, hashes and times, and no personal data.
- Let a sandboxed agent read the real dataset it was scoped to, through a copy it fetches itself over an isolated network, capped in size before a single byte moves.
Notebooks, storage and accounts
- Sign a notebook in without pasting a session: the notebook shows a code, the person approves it in the console, and the notebook receives a short-lived pass that the person can end. The notebook installs its client library from the platform itself with
pip. - Store each organisation's data in its own isolated bucket, and on Cloudflare R2 its own short-lived credential, so a leaked credential reaches one customer rather than all of them.
- Close down a customer account in two stages, hold it back while a legal matter is open, and produce its records as an encrypted, signed package that no single administrator can request and approve alone.
- Show what storage each organisation is using, on which backend, and free what is no longer needed, rehearsing exactly what would be removed before removing it.
- Write one line of log per event carrying identifiers and never contents, with anything resembling a secret redacted before it is written.
02 · Value to your organisation
The hard part is not storing the data. It is accounting for it afterwards.
An auditor gets an answer, not an assurance
"What did this model read, under whose authority, and who approved it" becomes a database query. Every decision to allow or refuse access was recorded at the time, together with the reason, so nobody has to reconstruct events from memory and old chat threads.
An incident can be traced with one query
Any suspicious output can be traced back in a single query to the exact code, software image and input data that produced it. Each agent run permanently records the version that actually ran, so deploying a newer version afterwards does not obscure what happened.
A prompt-injection attempt ends as a refusal
Because an agent's identity is held outside the model, the most a hidden instruction can achieve is to be refused and logged. There is no higher level of access for it to reach, because the permission check never reads anything the model produced.
Serious agent actions cannot skip human review
The review step is built into how the agent runs, not written down as a rule staff are expected to follow. The run stops before the significant step and can only continue once a second person approves it, and that person must belong to the same customer and must not be whoever started the run.
Publication rules keep working as data changes
Whether a dataset may leave the organisation is worked out from where it came from and what its licence permits, traced through everything that has been done to it. It does not depend on a person remembering to set a field correctly.
A leaked storage credential does not become a breach of every customer
Storage credentials are scoped to one organisation's bucket, rather than being one key shared across every customer. A credential that rests on an approved lease, or that is issued to a single task such as a pipeline step, a derivation run or an agent run, opens only the dataset versions that were allowed and ends with the lease or the task. On Cloudflare R2 every credential is short-lived. Losing one credential exposes only what it was scoped to, not the whole platform.
03 · See it working
Real screens, from real live runs
Each walkthrough follows one story step by step, with real screens captured from a running Munitas.
- Health organisation: 23 walkthroughs
- Finance organisation: 2 walkthroughs
- Harbour Clinic: 2 walkthroughs
Open the walkthrough index, which also says where to start →
04 · Core concepts
Seven ideas that the rest of the system is built on
The department that owns the data decides who may read it
Every dataset belongs to one department. Only that department's approvers can accept a request to read it, and any one of them can. Ownership therefore decides who may say yes, rather than seniority or whoever happens to be available, and the person asking can never be the one who accepts.
Access is for a purpose and for a limited time
A request names one dataset version, what the work is for and why it needs that data. An accepted request is a lease: it is tied to that purpose and ends on its own. If a lease is withdrawn, any dataset made from the data under it is closed too.
Widening access never moves the data
Every dataset version sits at one of five sensitivity levels, shown in the console in capitals. RAW is the original data and the most restricted. UNDER_REVIEW, OPEN_FOR_ANNOTATION and OPEN_FOR_TRAINING follow, each less restricted than the one before. PUBLISHED is generally available and the least restricted. Moving a version up to a less restricted level changes only which access credential opens it. The files themselves are never copied or rewritten, which was confirmed by checking that their storage keys and checksums are identical before and after.
Sensitivity and origin are two separate questions
Sensitivity decides who inside the organisation may read a dataset. Its origin decides whether it may leave the organisation at all. A public benchmark and a clinical dataset with names removed can be equally safe to read internally, while only one of them may be published. Treating these as one setting either blocks harmless downloads or releases regulated data as soon as it looks safe enough to read.
An agent's identity is assigned, never self-declared
An agent's identity is held by the program running it and is never part of the data the AI model can see or modify. Every time the agent tries to use a tool, its permissions are rechecked against that assigned identity. This is what protects against prompt injection, where an attacker hides instructions inside a document the agent reads. Such an instruction can change what the model asks for, but it cannot change who the system believes the agent is.
Deleting a person's data without rewriting history
A person's records can be erased permanently without editing any sealed dataset. The platform destroys the key the record depends on, so the record becomes unreadable everywhere it ever appeared, while the dataset versions and audit trail stay exactly as they were. A short marker is kept to record that the deletion happened, so the fact of the erasure is not itself erased.
Agents and releases are held to rules the organisation writes
An organisation writes its own risk levels for agents, and its own standards for what a de-identified result must meet before it is released. Both are named and versioned, and neither is ever edited: a change adds a version with who made it and why, and a decision keeps the version it was judged by.
05 · Architecture
Four layers, and one record across all of them
Munitas is arranged in layers. People work through the Console or a notebook. Every request passes the governance layer: sign-in establishes who the person is, the API receives the request, and the policy engine decides it. Work that runs code happens in the processing layer, and the three kinds of code that are not the platform's own, an organisation's custom pipeline steps, derivation queries and sandboxed AI agents, run in places with restricted reach. Files and tables live in storage, one bucket per organisation, with a key for each person whose data is locked. A record of every decision runs across all of the layers.
The picture is simplified. It shows the layers and the places with restricted reach, not every service or every connection.
06 · Who uses it
Eleven roles, and what each one does
Munitas has eleven roles that people hold. Every organisation is staffed from these same roles: someone who brings data in, someone accountable for each department's data, someone who asks to read it, someone who checks the decisions, an administrator who runs the platform itself, and so on. The entries below follow one example organisation, the health organisation used throughout this page. The finance organisation, covered in its own walkthroughs, is staffed by a different cast in the same roles. Each role signs in for real through Ory Kratos, and nothing can be approved, revoked or decided without that signed-in identity behind it. Open a role to read its steps. Each entry ends with the problem the steps solve.
Every person, including the administrator, can read published data by default and nothing more sensitive without a specific request that somebody else approves. Only the de-identification pipeline reads raw data, because removing personal information from raw recordings is the entire job it exists to do.
Ownership decides who may say yes. Hartley is a data custodian for Cardiology and Okonjo for Radiology: Hartley can approve access to Cardiology's data and cannot approve access to Radiology's, and Okonjo the reverse. A request goes to the people accountable for that particular data rather than to whoever happens to be senior or available. Every other role is barred from approving access. The data protection officer is excluded because approving access means deciding how data gets used, and GDPR Article 38(6) requires that an officer's other duties never create a conflict of interest with that oversight. The platform administrator is excluded because the account that operates the system should not also be able to grant itself access to what the system protects.
People who bring data in and use it
DeviData engineer
Brings data in, registers code and runs the jobs. Does not read what the jobs produce.
Brings data in, registers code and runs the jobs. Does not read what the jobs produce.
- Registers a new dataset, naming the department that owns it and where the data came from. The registration is refused if the department does not exist or the origin is left unstated.
- Loads the data in, either by uploading files or by importing from HuggingFace. The import runs in the background, so the screen responds immediately no matter how large the source is.
- Seals the version once loading has finished. The system refuses to seal it while an import is still running, so a version can never be sealed halfway through arriving.
- Uploads recordings for de-identification and seals them as recordings rather than as anonymous files. The platform reads each one and tells Devi its length and sample rate, so a truncated file is refused as it is added instead of surfacing later. If the set is incomplete, sealing is refused with every problem listed at once and nothing is sealed.
- Starts the de-identification personally, from the screen where the recordings were just sealed, instead of asking whoever has a terminal on the machine that does the work. Devi is refused, in writing and before anything starts, if the version holds ordinary files rather than recordings, if a recording arrived without the answer key the scoring needs, or if nothing is running to do the work. A refused start leaves nothing behind to clean up.
- Follows the run on its own page while it happens, step by step, rather than waiting without knowing whether it is working or stuck. At the end Devi is told it is waiting on a reviewer, and that Devi cannot be that reviewer, because Devi is the one who started it.
- Does not read the sensitive data the pipeline later produces from it. Running the loading process does not grant access to the results.
- Starts the triage agent against the review queue the pipeline left behind. Devi opens the agent, picks that dataset version, and says what the run is for.
- Is told before starting that the agent cannot read that data, which custodian would be asked, and that the request will be filed in Devi's name. Nothing is asked of anybody until Devi confirms.
- Sees the run listed as waiting for data access rather than as running. It has not begun, the screen does not pretend otherwise, and it moves only when the custodian decides.
- Registers an agent for a department and proposes a level for it. A new version that would let the agent do more waits for the approvals its level asks for, and nothing is deployed until they have said yes.
SamResearcher
Works with the published data of an organisation from a notebook.
Works with the published data of an organisation from a notebook.
- Requests access to one specific dataset version, stating what the work is for and why it needs that data. Blanket requests for a whole department are not possible.
- Waits for an approver of the department that owns the data. Only the approvers of that department can say yes, and any one of them can.
- Asks the system for access once approved. It checks whether the role already allows this, and if not, whether an approved and still-valid grant covers it.
- Receives a credential for their own organisation's storage only, and only after the decision has been written to the audit record. A credential that rests on an approved lease opens that one dataset version and stops working when the lease ends.
WrenAnalyst
Works with the data an organisation has published.
Works with the data an organisation has published.
- Opens the datasets an organisation has published and works with them. Published is the least restricted of the five sensitivity levels.
- Has no power of its own beyond reading published data. To see anything more sensitive, asks for access to one dataset version and gives the purpose, like anybody else, and an approver of the owning department decides.
- Cannot approve a request to read data, register code, or decide whether a de-identified result may be released.
People who decide who may read
HartleyCardiologyData custodian
Answers for the data a department owns, and decides who may read it.
Answers for the data a department owns, and decides who may read it.
- Checks claims about how sensitive a dataset is. If whoever registered it said the data is less sensitive than the cautious default, an approver of the owning department has to agree before that claim takes effect. A custodian may also bring data in, but never confirms their own claim: another approver of the department does, and a claim made by a department's only approver waits until a second approver has been added.
- Reviews access requests for Cardiology's datasets. Each request names a specific dataset version, what it will be used for, and why that use needs this data.
- Is refused when trying to approve a request for Radiology's data, because Okonjo is an approver of that department and Hartley is not. Ownership is what grants the authority.
- Approves or refuses. Hartley cannot approve a request of their own, or one somebody filed on their behalf. Both the policy engine and the database enforce this independently.
- Sees a written reason with every refusal, naming which rule caused it, rather than only an error code.
- Sees requests made for an agent in the same queue as requests made for a person, showing which agent will read the data and which engineer asked for it. Approving one starts the waiting run; refusing it closes that run with Hartley's reason attached, so nothing is left waiting on a decision that has already been made.
- Manages who the approvers of Cardiology are. Hartley can add a person who already holds the data custodian role, give temporary cover that ends by itself, or remove an approver. Every change needs a written reason and stays in the history, and at least one permanent approver who can act must always remain.
- When an organisation is being closed down, its custodian can still cancel during the first 15 days. When records are produced for a legal matter, the custodian named by the legal hold confirms what the package covers.
- Agrees to the first version of an agent owned by Cardiology, with the AI risk owner confirming its level. A version that adds only tools on the approved list needs at most the department that owns the agent.
People who oversee and check
ImaniDe-identification reviewer
Judges whether removing identifying details worked well enough for a result to be released.
Judges whether removing identifying details worked well enough for a result to be released.
- Opens a queue of finished pipeline runs waiting on a decision. Each one shows what the run scored, what the check recommends, and why it recommends it.
- Reads the identifiers that survived redaction, one row each: which record and which character positions it sat at, what kind of identifier it was, how much of it was removed, and how it failed. This is the material the judgement is made on, so it is shown rather than summarised into a score.
- Promotes the result, or holds it back. Either way Imani writes a reason, and neither is possible without one.
- Cannot decide a run Imani started. The database refuses it, not only the interface.
- Is the only role that may make this call. A custodian owns the data and would be judging their own department's output; an administrator operates the system and holds no standing access to what it protects; and the data protection officer is the one later asked whether the release was sound, which is not a question you can answer about your own signature.
- Is under no deadline, and neither is the queue. Nothing expires, escalates or promotes itself while a decision is outstanding.
NakamuraData protection officer
Watches how personal data is handled, sets the de-identification standards, and may stop an agent.
Watches how personal data is handled, sets the de-identification standards, and may stop an agent.
- Reads every access decision the platform has recorded, both grants and refusals, across every department and customer Nakamura is responsible for overseeing.
- Reads no more of the underlying data than any other member of staff. Being able to review decisions is kept separate from being able to see what those decisions were about.
- Cannot approve access requests. This keeps the oversight independent of the decisions being reviewed.
- Writes the organisation's de-identification standards. Imani chooses one when deciding a release, and a later change to a standard never changes what an earlier decision says.
- Can suspend an agent, and makes an evidence pack for an auditor: what the platform holds about one agent over a period, with no personal data in it.
OkaforAI risk owner
Answers for how the organisation holds its AI agents.
Answers for how the organisation holds its AI agents.
- Writes the organisation's risk levels, a short list that says how strictly each kind of agent is held: whether a change needs a second approver, how often the agent must be confirmed again, and whether it may be deployed at all. Every change is saved as a new version with who made it and why.
- Confirms the level of each agent, together with the first version, after an approver of the owning department has agreed. A first version is always decided by people.
- Writes the list of tools the organisation has approved in advance, each with the highest risk level it is approved for, the conditions it is approved under and a date to look at it again. A version that adds only listed tools is approved in advance.
- Can suspend an agent.
- Reads no more data than anyone else, and cannot approve access requests.
InesPrivacy auditor
Checks how locked data was used, from evidence that holds no names and no values.
Checks how locked data was used, from evidence that holds no names and no values.
- Reads the evidence of how locked data was used: who read it, who was refused, and which keys were opened. The evidence holds no names and no values.
- Makes the evidence pack of an agent and checks that its records have not been changed.
- Can ask for a short, approved lease to see the real values of locked data, for a stated purpose. Somebody else approves it.
- Can report an incident about an agent. Cannot approve a request to read data, so that the checking stays independent, and cannot register code or decide a release.
JoaquinNetwork architect
Decides which outside hosts an agent version may call.
Decides which outside hosts an agent version may call.
- Reads the outside hosts that a new agent version declares it needs to call.
- Approves or refuses each host and writes the reason. An approved version can then be deployed, and a refused one cannot.
- Cannot decide a version that Joaquin uploaded personally, cannot approve a request to read data, and cannot register code.
People who run the platform
PriyaPlatform administrator
Runs the platform itself, with no standing access to what is inside an organisation.
Runs the platform itself, with no standing access to what is inside an organisation.
- Keeps the platform running: starting services, monitoring jobs and traces, and freeing up storage. The last of these is done from a screen rather than from a shell: what each organisation is using, on which storage backend, what can be freed, and a rehearsal of exactly what a clean-up would remove before anything is removed.
- Closes a customer account when the relationship ends, in two stages. For the first 15 days the account is read-only, and the organisation's custodian can still cancel. For the next 15 days it is closed. After that everything inside it is deleted, unless a legal hold stands, and only a short record that the deletion happened is kept. A legal hold is recorded by one administrator and approved by a different one. Records for a legal matter are produced the same way: one administrator asks, a different one approves, and the custodian named by the hold confirms the scope. Nobody reads the records themselves, because the result is an encrypted, signed package.
- Holds the most powerful account in the system, and deliberately has no standing access to the data it protects and no ability to approve access requests for anyone, Priya's own included.
- Cannot change who holds which role, either. Anybody may ask to hold one and somebody else decides it, so the account that runs the system is not also the account that decides who may read what. The role that administers roles cannot be obtained from the running system at all: a second administrator is made the way the first one was, deliberately and from outside.
KitSupport and reliability
Keeps the platform running and supported, with telemetry and never records.
Keeps the platform running and supported, with telemetry and never records.
- Works from telemetry about how the platform is running, never from records.
- Sees the storage housekeeping record of every organisation, which names no data.
- Cannot approve a request to read data, and cannot reclaim storage or close down an organisation.
Automated roles
De-identification pipelineAutomated
Strips personal information out of recordings, and releases nothing.
Strips personal information out of recordings, and releases nothing.
- Works through six steps to strip personal information out of audio recordings: transcribe, detect identifiers, hand off for human correction, replace the identifiers, measure what was missed, and write down what it found for a reviewer to decide on. Names in the transcript are replaced with consistent substitute names, and the matching stretch of audio is overwritten with low-level noise of the same length, so the timing of the recording is kept.
- Saves its progress after each recording while it transcribes, which is the slowest step, so a transcription that fails partway through resumes rather than starting again.
- Is the only account that reads raw, unredacted data, because removing personal information from raw recordings is exactly what it exists to do.
- Records whether each run was started by a person or by a schedule, so there is never any doubt about what set it off.
- Releases nothing, whatever it scored. Its last step records what it found and the pipeline ends there, waiting on a reviewer, whether the score passed the standard or not.
- Gives every step of a run the same identifier, so a run that grows into more than one workflow is still one traceable execution rather than several unrelated ones.
Background workersAutomated
Run the long jobs away from the process that holds every credential.
Run the long jobs away from the process that holds every credential.
- The derivation runner executes the query that makes a new dataset, inside an isolated container with no network connection and no passwords. The platform checks the result before the new dataset appears.
- The table worker writes large tables in the background as a job, so the screen responds at once however large the table is.
- The closing sweep runs on a schedule and moves an account that is being closed down from one stage to the next when its date arrives. An account under a legal hold is not deleted.
Triage agentAutomated: AI agent
Ranks the queue of transcripts so the riskiest are checked first.
Ranks the queue of transcripts so the riskiest are checked first.
The job it does. When the pipeline has finished detecting personal information in a batch of recordings, it leaves a queue of transcripts for a person to check, because a missed identifier is a leak and only a human confirmation closes that risk. The queue is normally far longer than reviewers can work through in a day. This agent reads each waiting transcript and ranks it high, normal or low with a one-line reason, so the riskiest are checked first instead of whatever happens to be at the top of the list.
A transcript in that queue looks like this, with the identifiers still in place because that is exactly what a reviewer is there to confirm. The name and the date of birth are invented:
clinician: Right. Let me pull up the notes. Eoghan Bell, born 12 February 1965, is that correct?
It produces a judgement and nothing else. It cannot release data, change anyone's permissions, or read a dataset on its own authority.
- Is deployed as one specific sealed version, identified by the exact code it contains. Deploying a newer version while a run is in progress does not change which version that run is using.
- Cannot read the review queue by default. The queue holds unredacted transcripts, so it is held at the most restricted level, and this agent is trusted only with published data.
- Gets access the same way a person would. Starting a run against data it cannot read files a request naming the agent as the reader and the person who started the run as the one who asked. The custodian who owns that data approves it, and that approval is what sets the run going.
- Runs under an identity held by the surrounding program, not by the AI model. An instruction hidden in a transcript cannot change the identity its permissions are checked against.
- Raises any document that appears to address it to high priority, rather than doing what it says. Text aimed at the reader is itself a reason for a person to look at that document.
- Stops before its final step and reports that it is waiting for sign-off, rather than reporting success it has not earned. A different person accepts the findings, and the paused state is stored so that can happen days later.
- If it runs sandboxed rather than natively, and its version declares it needs a copy of the data, fetches that copy itself over an isolated network only after the same access decision above has been granted, capped at a fixed size before a single byte moves.
07 · How it is measured
What is measured, and what each measure decides
Two parts of the platform turn measurements into action. The pipeline that removes personal information is measured on accuracy, because the risk is that it misses something. A person decides what to do with those numbers. An agent run is measured on consumption, because an agent that gets stuck in a loop does not crash: it carries on working, producing reasonable-looking output and occupying the machine. The platform stops that run on its own.
Removing personal information: accuracy
These figures come from comparing the pipeline's output against a known answer key. The recommendation the reviewer is shown when deciding whether a result may be released to a wider audience is made by comparing them with a de-identification standard. A standard is a set of limits the organisation chooses: one for all identifiers together, and one for each kind of identifier (names, dates, phone numbers and the others).
A standard is kept under a name for the audience it is for, such as a closed research team or a public release, and whoever releases a result chooses which standard to judge it by. Every organisation starts with the Platform default standard: at least 98 percent of identifiers removed, and none of the five kinds that name a person directly (a name, a record number, a national identity number, a phone number or an email address) left in the clear.
That is a starting point, not a verdict. Only the organisation's data protection officer sets a standard, and every change is kept as a new version with who made it and why. The remaining figures are recorded and help explain a poor score.
| Measure | What it tells you | Used for |
|---|---|---|
| Recall after transcription | Of the identifiers that were still readable in the transcript, the share the pipeline removed. This is the fairest measure of the pipeline's own work, because it excludes names the speech recognition had already garbled beyond recognition. | Below the standard's overall limit (98 percent in the Platform default standard) so the recommendation is fail |
| Recall for each kind of identifier | The same share, counted separately for names, dates, phone numbers and every other kind of identifier, so that a good overall figure cannot hide one kind that is being missed. | Below the standard's limit for that kind, where it sets one, so the recommendation is fail |
| Identifiers left in the clear | Identifying text that survived, whole or in part, such as a full name or an email address still in plain sight, or a surname with two letters changed. | Above the standard's limit for that kind (none in the Platform default standard) so the recommendation is fail |
| Recall against everything spoken | The same share, but measured against every identifier actually said aloud, including ones the speech recognition destroyed by accident. Always the lower of the two figures. | Recorded only |
| Identifiers never found | How many of the leaked identifiers the detectors never marked, even in part. | Recorded only |
| Share destroyed by transcription | How many identifiers the speech recognition had already mangled before the pipeline saw them. | Explains a score |
| Transcript accuracy | How closely the transcript matches what was actually said. This separates a pipeline that failed to redact from one that was given a bad transcript to work with. | Explains a score |
These numbers, with the counts for each kind of identifier, are stored on the decision record itself, not only in the experiment tracker, so the reason a dataset was released stays available even if the older run history is cleared out. The decision also records which standard it was judged by, that standard's version and its limits as they were, so a later change to a standard never changes what an earlier decision says. A run that falls short of its standard is not released automatically: it is shown to a reviewer as a fail recommendation.
The recommendation is advice, and the pipeline acts on none of it. It stops there and a person decides, because a threshold can only measure what the answer key already knows about, and the reviewer is looking at the identifiers that survived rather than at a number standing in for them. A pass is not a release either: an unreviewed result stays where it is until somebody signs for it.
Agent runs: consumption limits
Every run is given two ceilings. The program running the agent enforces them, rather than asking the AI model to respect them. Crossing any one stops the run immediately and records which limit was hit.
| Limit | Default | Why it exists |
|---|---|---|
| Tool calls per run | 25 | Caps how many times one run can reach for data or take an action |
| Seconds per run | 300 | Caps elapsed time, so a run that is waiting on something rather than looping is also stopped |
Alongside these limits, each run keeps a running count of its tool calls and a full record of every access decision those calls produced. The count adds up across a pause and resume rather than restarting, so approving a paused run cannot hide what the first half already spent. An automated test confirms that a task written to loop forever stops at the tool-call limit.
08 · Cost and return
What it costs to run, and which recurring work it removes
Two things drive the return: what the platform costs to run, and which expensive manual work it removes entirely. Both are described below, so each can be set against your own organisation's numbers.
Software licences: nothing
The platform and every service it runs are under open-source licences that allow commercial use, almost all of them MIT, BSD or Apache. Three small libraries are under the Mozilla Public Licence 2.0, which applies file by file and asks for nothing unless you change those files. Speech recognition on a graphics card also uses NVIDIA's CUDA libraries and the FFmpeg audio library, which you install on that machine under their own licences: NVIDIA's are free to use commercially but are not open source. So there are no per-seat charges, no per-machine governance fees and no renewals to negotiate.
Running an agent: hardware, not usage fees
The agent's AI model runs on the machine's own graphics card instead of a paid external service. The cost of a run is therefore the cost of the hardware the platform runs on, rather than a bill that grows with every request. The per-run limits in section 7 cap how much of that hardware any single run can occupy.
Removes: reconstructing an audit trail
Answering "what did this agent read, and who approved it" is a query against records written at the time. The alternative is piecing the answer together from logs, chat history and recollection, which also produces a less reliable answer.
Removes: tracing a bad output by hand
A suspicious result can be traced to the exact code and input data behind it in one query. Doing the same without recorded lineage means manually working out which run, which code revision and which data were involved, under time pressure.
Removes: arguing about whether a release was safe
The figures from section 7 and every identifier that survived are attached to the decision record, along with who accepted them and why. The judgement still belongs to a person, but it is made once, on evidence everyone can see afterwards, rather than re-argued from memory in a meeting.
Caps: a stuck agent has a known worst case
A run that loops instead of finishing is stopped by the two ceilings in section 7, so the worst case is bounded rather than however long it takes someone to notice.
09 · Components, and why
What it is built from, and why each part was chosen
Licences are covered in section 8. Permissive licences for the platform itself were a hard requirement, and they ruled out several otherwise strong options.
Storage, control and policy
| Component | What it does here | Why this one |
|---|---|---|
| SeaweedFS | Stores the actual data files, the default storage backend | It supports credentials limited to one folder, or to one organisation's own bucket, which is how a sensitivity level becomes a physical restriction rather than a rule the application is trusted to apply. Every organisation's ordinary ingest and agent-upload writes go through that organisation's own standing identity, never a shared admin key. It also speaks the same interface as Amazon S3, which is why the same code runs against Cloudflare R2. |
| Apache Iceberg and DuckDB | Lets a person open a table with a standard analysis tool, through the platform | Iceberg is an open way of storing a table, and DuckDB is a free tool that reads it. The platform lists only the tables the person may read, and hands the tool a short-lived key for the files of the one table opened. The derive walkthroughs show this running with real DuckDB. |
| Cloudflare R2 | A second, optional storage backend, chosen per organisation | Zero egress fees, which matters because a sandboxed agent's own copy of its data is egress-heavy. Each organisation on R2 gets its own bucket and its own short-lived, bucket-scoped credential, the same shape SeaweedFS's own per-organisation identity takes. |
| PostgreSQL | Stores all records, history and audit entries | It can enforce rules the application cannot bypass, which is what makes sealed datasets genuinely immutable. |
| Temporal | Runs long jobs: the pipeline, imports and agent runs | It records the state of a job durably, so retries, timeouts and resuming after a crash are provable behaviour, not a description of intent. This is what lets an agent pause for days awaiting approval. |
| Open Policy Agent | Decides every access, approval and publication question | Keeping the rules in one testable place means access policy can be unit-tested like code. It returns a reason with every decision, which is what makes the audit trail meaningful rather than a list of yes and no. |
| Ory Kratos | Handles real sign-in for every human role | Chosen over Keycloak for its lower memory ceiling on a single machine. An identity always comes from a session Kratos issued, never from a name the caller supplies. |
| Ory Hydra | Signs a notebook in on a person's behalf | It issues, renews and revokes a short-lived pass, and holds nothing about who people are: Kratos still answers that, and the platform's own API decides what a pass may do on every request. A pass is opaque and not signed, so it can be revoked at once. |
| FastAPI | The single interface everything else goes through | It validates incoming data against a declared shape automatically, so malformed requests are rejected before reaching any logic. Keeping this layer thin was deliberate: rules belong in the policy engine and the database, not scattered here. |
| Munitas console | The web app people open in a browser | It asks the API for everything it shows, so what a person sees comes from the same decisions as everything else. |
| Munitas client library | Lets a person work from Python or a notebook | It sends requests to the API, so the same access decisions apply as in the console. |
| Derivation runner | Runs the query that makes a new dataset | It runs in a container with no network connection and no passwords, so a query cannot send data anywhere or reach anything it was not handed. |
| Step gateway | The one way a custom pipeline step reaches the platform | A step runs on a network with no route to the internet, and the gateway is the only other thing on it. It forwards only the platform's step routes to the API and answers 404 to everything else. |
| cryptography (Python) | Encrypts records and stored credentials | It is the standard, well-reviewed Python library for this, and keeping the key for a record apart from the record is what allows permanent deletion without altering any sealed dataset. |
Removing personal information from recordings
| Component | What it does here | Why this one |
|---|---|---|
| faster-whisper | Turns audio into text | It reports the exact timing of every word, which is required to mute the right moment in the audio and not just the text. |
| Presidio, spaCy and GLiNER | Three separate detectors that find personal information | They fail in different ways. Presidio matches known patterns such as phone numbers, spaCy recognises names it was trained on, and GLiNER catches categories nobody trained it for. Combining all three means a miss by one can be caught by another, which matters because a single miss is a leak. |
| Label Studio | Lets a person correct what the detectors found | It can be pre-filled with the detectors' output, so reviewers correct existing marks rather than starting from an empty transcript, which is far faster and more consistent. |
Agents, models and monitoring
| Component | What it does here | Why this one |
|---|---|---|
| LangGraph | Defines the agent's steps and where it pauses | The agent's possible paths are written out explicitly rather than left to the model to decide, so the approval pause is a property of the structure. The model cannot skip it. It also saves the paused state so a run can be resumed later. |
| Ollama | Runs the AI model | The model runs on the machine's own graphics card, so no data or prompt is ever sent to an external service. For regulated data this is often the difference between a system being permissible and not. |
| OpenTelemetry and Jaeger | Records and displays what happened during a run | OpenTelemetry is a vendor-neutral standard, so the monitoring backend can be swapped without changing the application. Each trace is tagged with the sensitivity of the data involved, making it visible if sensitive data reaches a place it should not. |
| MLflow | Stores measurement results from pipeline runs | It is the established open tool for tracking runs and their scores, and it gives the release decision in section 7 a permanent record to point back to. It has no sign-in of its own here, so what it is given is deliberately limited: the position of each identifier that leaked, never the identifier itself. |