TrustFill documentation

TrustFill puts your AI agent to work inside the security questionnaire your customer sent you, in their own portal, while a person accepts or corrects every answer. This is how to connect it, how to teach it a new portal, and how to read the record it produces.

The shortest possible description

A person opens the questionnaire in a shared browser session and logs in themselves. Your agent reads the questions through a small set of tools, drafts answers with its reasoning attached, and enters only the ones it can source into fields that are empty. Everything else waits in one list. Every answer, correction and reason is written to an append-only journal you can export.

Which half of this is for you#

If you are wiring it up

Read Connect your agent, the answer contract and adapters. The first takes about as long as making a coffee. The third is ours to do, not yours.

If you are signing it off

Read the supervision boundary, what is stored and where, and the journal. Those three answer most of what a security review of this tool will ask, and the journal is the part that makes your own answers defensible later.

The Webfuse space#

engineersecurity team

TrustFill does not drive a browser on a server somewhere. It works inside a Webfuse session: a live browser that a person and an agent share. Webfuse is a web-augmentation proxy — the page is real, the session is shared, and an extension installed into the space can expose page-level capabilities as tools an agent can call over MCP.

Three consequences worth being precise about, because they are what a security review turns on:

You do not configure any of this

The space, the extension, the keys and the session plumbing are infrastructure we run. There is nothing to sign up for and no keys for you to keep in step. Powered by Webfuse means exactly that: you bring your agent, we bring the surface it works on.

Settings → Live session reports three capabilities so you can see it is working, and so that when nothing happens you know which one is missing rather than guessing:

CapabilityWhat it meansIf it is not working
Open a session A live browser can be started for you. Nothing starts at all. Tell us.
Read and fill a page The co-pilot can read the questionnaire and type answers into it. The session opens and the co-pilot cannot see the page.
Tidy up old sessions Sessions nobody is using any more get closed. An abandoned session can block a new one. Symptom: “Tab owner is not connected”.
One session per questionnaire

You cannot work one questionnaire in two sessions. A session left open with no browser tab attached looks perfectly healthy — it is listed as active and its join link still renders the portal — but every tool call against it fails with “Tab owner is not connected to the session”. TrustFill closes earlier sessions on the same questionnaire when you open a new one, and says so in the journal.

Connect your agent#

engineer

TrustFill does not answer questions. It asks your agent, over MCP, and refuses to let anything else produce an answer. Connecting one is three fields and a contract.

  1. Point it at your agent In Settings → Agents, set the intelligence agent's MCP endpoint, its key, and which tool to call. Leave the tool blank if your server exposes exactly one — TrustFill will use it rather than guess between several.
  2. Choose how the question is sent Typed fields sends the question, its options and the context as named arguments. One message folds all of it into a single string, which is what a conversational agent needs. If your agent's only input is something like message, pick One message and set the question argument to match.
  3. Add anything else the tool requires Some hosts need arguments that have nothing to do with the question — a project, a thread id, a timeout. Put them in Extra arguments as JSON and they travel with every call.
  4. Answer in three lines See the contract. The third line is the one that decides whether an answer can be entered without a person.

A worked example: an Atlas-hosted agent

# Settings → Agents → Intelligence
Name              Themis
MCP endpoint      https://atlas-mcp.example.com/atlas-you/mcp
Tool              atlas_send_message
Question argument message
Payload           One message
Auth header       X-Atlas-Mcp-Api-Key      # not Authorization
Value prefix      (empty — the key is sent bare)
Answer path       response                 # the reply is wrapped
Extra arguments   {"project": "atlas-you",
                   "thread_id": "8e8f1cdd-…",
                   "timeout_seconds": 300}
Why the header fields exist

A correct endpoint and a correct key still return nothing if the header is called something else. Atlas wants its key in X-Atlas-Mcp-Api-Key with no Bearer prefix at all — a client that can only send Authorization: Bearer cannot reach it. That is a five-minute debugging session the first time and never again.

The answer contract#

engineersecurity team

Your agent replies with three lines. Two are for the record; the third is a safety catch.

ANSWER: Yes
WHY: Password rotation every 90 days is set in the platform baseline, section 4.2.
BASIS: sourced
LineWhat it must beWhat TrustFill does with it
ANSWER One of the options actually on the page, verbatim. For a free-text question, the answer itself. Checked against the real control before anything is typed. A value that is not on the page is refused, not approximated — “No” never quietly becomes “Not Applicable”.
WHY One sentence naming what the answer was based on. Stored with the answer, shown to the reviewer, and carried forward as precedent. This is what makes a correction teachable rather than just annoying.
BASIS sourced, inferred or unknown. Only sourced is entered unattended, and only into a field that is empty. Everything else waits for a person. An agent that invents a fourth word is treated as unknown.

An agent that cannot answer should say so rather than guess. Reply with ANSWER: needs human — or anything containing “needs human” — and TrustFill records the refusal, with your reason, as an action item. A refusal in the record is worth more than a plausible answer nobody can source.

The rules that are never relaxed

Never overwrite an answer that is already there. Never enter an answer that is not sourced. Never enter a value the control does not offer. Never submit the questionnaire. Every one of those is a human action, every time.

One agent or two#

engineer

TrustFill has two agent slots, and most installations should use one. The switch marked One agent does both jobs is the normal setting, not the degenerate one.

Intelligence — answers

Knows your security posture. Given a question, its options and the context, it produces an answer, a reason and a basis. This is the one that matters and the one you must configure.

Harness — drives

Reads the questionnaire, works out the scope, walks the sections, asks the intelligence and types what you accept. Today this is TrustFill itself. The slot exists so the journal can attribute a decision to something other than a person, and so the configuration is already in the right place if the driving ever moves to an external agent.

When a second agent is genuinely worth it

If none of those apply, one agent is the better answer. Two endpoints is two things to keep in step, and an installation where the second is subtly stale is worse than one where it never existed.

Making the agent better#

engineersecurity team

Answer quality is almost entirely a function of what your agent can retrieve, not of how the question is phrased. In rough order of how much difference each makes:

  1. Give it your real documents, not a summary. The policy, the SOC 2 report, the DPA, the architecture description, the pen test summary, previous questionnaires you have answered. A questionnaire asks about the same forty controls in a hundred phrasings.
  2. Feed it the journal. Your reviewers' corrections are the most valuable training data you will ever get for this task, because each one is a real disagreement with a real answer, on a question you will be asked again. See feeding it back.
  3. Make it say unknown comfortably. An agent rewarded for always producing an answer will produce confident wrong ones, and on a compliance questionnaire that is the expensive failure. TrustFill treats a refusal as a successful outcome; your prompt should too.
  4. Have it cite. WHY is not decoration — a reviewer accepting fifty answers reads the reason, not the answer. “Section 4.2 of the platform baseline” gets an accept in two seconds; “industry standard practice” gets a correction.
  5. Keep deal context current. TrustFill passes what was stated at intake — product, deployment model, MRR band, features in scope. An answer about data residency depends on it.
What TrustFill sends with every question

The question and its options, the section it sits in, the prospect and questionnaire names, the deal context, your house rules, and up to twelve ranked precedent entries from the journal. Precedent is ranked, not dumped: the same question coming round again outranks the same customer, which outranks the same questionnaire, and an answer a human changed outranks one they waved through.

Adapters and calibration#

engineer

The tools your agent calls are identical on every portal. What differs is detection: how a vendor lists its sections, what words it uses for its own progress counter, which class name means a row is open. Those live in a profile — one per domain, stored as data, sent along with each tool call.

This is the honest version of “works with your portal”. It is a driver model: a new portal is a profile, not a release, and the interface your agent talks to never moves.

What happens the first time

  1. TrustFill says it has not seen this portal Open the questionnaire itself — the actual question list, not a summary page — and then hand over.
  2. It looks, without clicking A read-only probe works out whether questions are numbered, how sections are listed, what the counter says, which marker distinguishes the open row, where an explanation box sits, and whether the questionnaire is inside an iframe. Every finding comes back with the evidence behind it.
  3. It proves the profile before trusting it Then, through the production path: read the section list with the candidate profile and check the totals add up to the figure the portal prints about itself; open a section that is not the open one and check the question list actually changes; put the view back. A profile that fails any check is stored unverified and is not used to answer anything.
  4. It tells you what it concluded In plain words — “32 sections listed with their own progress, questions numbered on the page, explanations beside the choice they explain” — before a single answer is drafted.
Why the verification matters more than the probe

A wrong profile does not crash. It makes the co-pilot read the wrong parts of a questionnaire and report itself finished — which is the one failure this product exists to eliminate. Predicting a number the page prints about itself is cheap, checkable, and catches almost every way a profile can be wrong.

What a profile holds#

{
  "v": 1,
  "navigation": "rows",           // rows | tabs | dropdown | wizard | single
  "numbering": "printed",         // printed | none
  "iframe": false,
  "sectionCount": {
    "pattern": "(\\d+)\\s*(?:of|\\/)\\s*(\\d+)\\s*questions?\\s*answered"
  },
  "activeMarkers": {
    "attrs": ["aria-selected"],
    "classes": ["active"]
  },
  "reasonBox": "sibling-of-container", // or inside-container | none
  "notes": "derived by probe on portal.example.com"
}

Profiles are visible in Settings → Portals, with the checks that were run, what each found, and the raw JSON. Nothing is deleted: retiring a profile is how you revert to the one before it, and the newest live profile for a domain wins. A domain can also be written as *.vendor.com to cover a vendor's subdomains, and an exact host always beats a wildcard.

Profiles are keyed on domain and a coarse page fingerprint. The same vendor serves several questionnaire types, and a white-label deployment sits on the customer's own domain running the same app — so if the page no longer looks like what the profile was derived from, TrustFill re-calibrates rather than proceeding on an assumption.

When a portal is not recognised#

Calibration handles five navigation shapes: a list of section rows with counters, tabs, a dropdown, a next-and-back wizard, and one long page. A portal that is none of those is reported rather than guessed at — which is deliberate, because a sixth way of moving through a questionnaire, invented on the spot, would be wrong subtly rather than obviously.

What you seeWhat it meansWhat to do
“This page has no sections to walk” A one-page form, or the section list is worded in a way the probe could not read. Fine for a short questionnaire. For a long one, send us the portal — writing a profile by hand is our job, not yours.
“Reports N unanswered but I could not reach them” The section opens but its questions are not in the page — usually lazy rendering the sweep did not reach. Report it. This is a profile problem, not a portal we cannot support.
“Looks like it is inside an iframe” The questionnaire renders in a child frame. The extension reads the top frame only. Needs an extension manifest change and a new session — not a profile. Tell us and we ship it.
“Section totals do not match the portal's own count” The profile is reading something other than the section list. This is exactly the failure that verification exists to catch. Nothing is answered. Re-calibrate, or send us the page.

The journal format#

engineersecurity team

Everything that happens is a row in an append-only journal. Nothing is ever rewritten: a correction is a new row that points at the old one. That property is what makes the journal usable as evidence, and it is not negotiable in the design.

Your whole compliance team can work in the same questionnaire, and every review, correction and sign-off is recorded against the person who made it. The journal is readable only by your administrators — it is your team's working history, not something your customer sees and not something we look at.

ColumnMeaning
idMonotonic. Order is meaning here: “the decision after this draft” is a forward scan.
run_idWhich sitting. One questionnaire worked over three days is three runs, threaded by portal URL.
kinddraft · decision · narrative · error
qrefThe question as the portal numbers it — 107, or 111.reason for the explanation box beside a choice.
authoryou, the agent's id, or app. An answer with no author is an answer nobody stands behind.
payloadJSON. Shape depends on the kind — below.
created_atUTC.

The four kinds

// draft — an answer from the agent. Only /ask can create one.
{ "text": "Yes", "why": "Set in the platform baseline, 4.2",
  "basis": "sourced", "question": "114.Do you have a procedure…",
  "options": ["Yes", "No", "Not Applicable"], "section": "Access Control" }

// decision — what was settled, and by whom. `text` is what it was before.
{ "text": "Yes", "final": "No", "why": "Not for contractors",
  "source": "direct-edit", "needs_reason": true }

// narrative — something happened, or something needs a person.
{ "text": "216 needs a document from you: …",
  "needs_document": true, "held_for_review": "only a person can attach a document" }

// error — it did not work, and why. Never silent.
{ "text": "Could not enter 118: not_set. The answer is drafted and waiting for you." }

Three conventions that matter when you read it

The Markdown export#

One file per questionnaire, across every sitting. This is the deliverable: a person can read it, it diffs in a repository, and it is already the native input of every agent framework worth plugging in.

GET /api/runs/:id/journal.md          # the whole questionnaire, all sittings
GET /api/runs/:id/journal.md?thread=0 # this sitting only
# Concentrix — Third Party Risk Assessment

- **Portal** https://portal.example.com/SecurityQuestionnaires/Receive/…
- **Attempts** 3, first opened 2026-09-07 09:14
- **Questions recorded** 41
- **Answers a person changed** 12
- **Answers carrying a reason** 29
- **Documents requested** 8
- **Exported** 2026-09-09T13:24:11Z by TrustFill

## What this file is for

Every answer given on this questionnaire, with who gave it and why. Feed it to
the agent that answers your security questionnaires: the entries marked
**corrected** are the ones that teach it something…

## Corrections — read these first

| Question | The agent said | A person changed it to | Why |
| --- | --- | --- | --- |
| 107 | Yes | No | We do not do this for contractors |
| 111 | Not Applicable | No | We do revoke, just not within 24h |
| 143 | Annually | Quarterly | Changed after the 2026 audit |

## Every question

### Access Control

**114** Do you have a procedure to change default passwords?
- Options: Yes · No · Not Applicable
- Drafted by Themis: **Yes**
- Final answer: **Yes**
- Why: Standard hardening step in the platform baseline
- Status: accepted as drafted
- Decided: 2026-09-08 11:02

## Documents this questionnaire asked for

Only a person can attach these, so they are listed rather than answered.

- **216** Kindly attach the detailed documentation of the program.
- **224** Please attach the report of the application Pen Test.

The corrections come first because they are the only part that teaches anything. Everything else is the complete record, in section order.

Four things to do with it#

1 · Answer next quarter's questionnaire in a fraction of the time

security team

The same forty controls come round in a hundred phrasings, and the same customer re-assesses you annually. Feed last quarter's export to your agent and the questions you already settled arrive pre-answered with the reasoning you approved. The measurable number is the correction rate: how often a reviewer disagrees with the draft. If it is not falling across questionnaires, the loop is not connected.

2 · Evidence for your own audit

security team

An auditor asking “who asserted this, on what basis, and when” has a bad time with a spreadsheet and an easy time with an append-only record. Every answer names its author — a person or a specific agent — carries the reason given at the time, and cannot have been edited after the fact. The document requests are listed too, so “we said we would send the pen test report” is checkable.

What it does not do

TrustFill is not an auditor and asserts no compliance. It records who answered what and why. The answers, and their accuracy, remain yours.

3 · Handover without a meeting

security teamengineer

A reviewer picking up somebody else's half-finished questionnaire reads the corrections table and knows the house line on the twelve contested questions in two minutes. The alternative is a call, and the call does not leave a record.

4 · Find out where your posture is actually weak

security team

A question your agent repeatedly cannot source is a gap in your documentation — or in the control itself. Grep the export for BASIS: unknown and needs a document across a few questionnaires and you have a prioritised list of what to write down or go and fix. Most teams find that list more useful than the questionnaire it came from.

Feeding it back to your agent#

engineer
We do not retrain your agent

Deliberately. Every agent is built differently, and reaching into yours is not our business. TrustFill produces the intelligence in a form a person can read and an engineer can wire up in an hour. What follows is a pattern, not a product.

The simplest thing that works, and what most teams should start with:

  1. Export after each questionnaire curl the Markdown endpoint into the repository or bucket your agent's retrieval already indexes. It is one file, and it is idempotent — export it again after more work and you get the current state.
  2. Index the corrections section with a high weight Those rows are question–answer–reason triples that a human approved. They are worth more than any other document you have for this task.
  3. Prompt your agent to prefer them “Where a previous correction covers this question, follow it and cite it.” That one sentence is most of the value.
  4. Measure the correction rate Count Answers a person changed against Questions recorded in each export. Falling means the loop works; flat means the file is being stored, not read.
# after a questionnaire is done
curl -s -H "Authorization: Bearer $TRUSTFILL_TOKEN" \
  "https://trustfill.tech/api/runs/$RUN/journal.md" \
  -o "corpus/questionnaires/$(date +%F)-$CUSTOMER.md"

# then whatever your agent already does with corpus/

What is stored, and where#

security team
WhatWhereNotes
Questions, answers, reasons, corrections SQLite beside the app, on a persistent volume Append-only. Exportable as Markdown, and optionally mirrored to any S3-compatible bucket you own.
Your portal credentials Nowhere. Typed by a person into the real login page inside the session. TrustFill never receives them.
TrustFill passwords users table scrypt with a per-user salt. The password is never stored, logged or returned — a copy of the database does not let anyone in as anybody.
Sign-in sessions user_sessions table Only the SHA-256 of the token. The cookie is httpOnly, SameSite=Lax and Secure over https.
Password reset links pw_resets table Hashed, single-use, one hour. Issuing a new one kills the old, and spending one signs out every session for that account.
Agent keys, space keys Environment or the settings file Write-only in the panel: the server reports whether a key is set, never what it is.

Accounts are disabled, never deleted. An answer is attributed to the person who gave it, and removing the person orphans the attribution. Disabling closes the door and ends their live sessions immediately.

Where your journal lives — and why we ask

The first time an administrator signs in, TrustFill makes them answer one question: your own S3-compatible bucket, or here with us? It is asked rather than defaulted, because the default — us holding your compliance record — is not something anybody chose.

ChoiceWhat happensWhat to know
Your bucket
recommended
Your journal is written to your bucket as you work. We keep the questionnaire you are actively on — a live session has to be transactional — and once it is closed and the write has been read back, our copy is deleted. Resuming next quarter loads it from your bucket for the length of the session and then lets it go. Any S3-compatible endpoint: AWS, R2, MinIO, Wasabi, Backblaze. We write a test object and read it back before accepting the credentials, so a wrong endpoint fails now rather than on your first questionnaire.
Here with us The journal stays in TrustFill's own storage. Requires an explicit acknowledgement, because the consequence is not obvious: we hold your compliance record, and if more than one person runs their own install then each keeps only its own copy — there is no single record of what your team decided.
Why we still keep the live questionnaire

A session writes as it goes and has to be able to read back what it just wrote — a draft, then the decision on it, then the write to the page. Doing that across a network to object storage would make the co-pilot slow and occasionally wrong. So the questionnaire in front of you is local, it is mirrored to you continuously, and it is gone from us when you close it.

A verified mirror is a precondition of deleting anything. Three conditions, all required: you asked for session-only retention, the mirror covers every local row, and no sitting is still open. A questionnaire somebody is working on is never purged.

What we do not keep

Worth being exact about, because the loose version of this claim falls apart in a security review and the precise version is still strong.

The journal — which question was asked, what was answered, who answered it and why — is the one thing that is kept, because it is the product: it is what makes the next questionnaire cheaper and your own audit answerable. With a bucket configured it is kept by you, in your storage, readable only by your administrators and never seen by your customer.

The supervision boundary#

security teamengineer

This is the part worth reading twice, because it is what a review of this tool turns on. The constraints are structural, not policy — there is no argument you can pass to relax them.

When something does not work#

engineer
SymptomCauseFix
“its handler did not register in time — reload the page and retry” The page tools are served by a content script injected per page load. If that injection was missed, every tool call fails with this, forever — retrying does not help because nothing is coming. Reload page in the session bar.
“Tab owner is not connected to the session” The session is alive but has no browser tab attached — usually a second session was opened and this run points at the abandoned one. Close the session and open it again. Retried automatically for about twenty seconds first.
“0 questions in scope” on a questionnaire that clearly has gaps Almost always the section list could not be read — so only the section on screen was visible. Check Settings → Portals for an unverified profile. Re-calibrate.
Answers drafted but never entered The basis was inferred or unknown, the field already had an answer, or the value was not one the control offers. All three are refusals by design. The reason is on each item in Action required. Nothing is hidden.
Password reset says no email was sent No mail provider is configured, or the sending domain is not verified. The link is handed to the admin instead. Set MAIL_PROVIDER and verify your domain.

Reference#

Environment

Platform settings live in the environment, not in the panel — one deployment, one value, and a form that could change them would be a way to redirect somebody's password reset.

# who may sign in
ADMIN_TOKEN=…              # opens the panel; how you make the first account
PORTAL_PASSWORD=…          # optional shared sign-in, still honoured
PORTAL_API_TOKEN=…         # for machines
SESSION_DAYS=14
RESET_MINUTES=60

# sending mail (resets only)
MAIL_PROVIDER=resend       # none | resend | postmark | custom
MAIL_API_KEY=…
MAIL_FROM=TrustFill <no-reply@your.domain>
PUBLIC_BASE_URL=https://your.domain

# the Webfuse space
WEBFUSE_DEFAULT_SPACE=…
WEBFUSE_SPACE_ID=…
WEBFUSE_SPACE_REST_KEY=…
SESSION_MCP_URL=…
SESSION_MCP_KEY=…

# the answering agent (or set it in the panel)
ANSWERER_MCP_URL=…
ANSWERER_MCP_TOKEN=…
ANSWERER_MCP_TOOL=…
ANSWERER_MCP_ARGS={"project":"…"}

The page tools

Eleven, exposed to your agent through the session's MCP server. Read-only unless noted.

ToolWhat it does
readQuestionnaireEvery question in the open section as data — number, text, options, current value, required, control type.
questionnaireSectionsThe whole shape: every section, how many questions, how many answered.
openSectionActs. Opens a section and confirms the question list changed.
awaitQuestionnaireBlocks until the page is really there and the count has stopped moving.
questionnaireStatusCan this be read yet, and what is in it.
questionnaireProgressAnswered, total, remaining — the portal's own figure.
nextUnansweredQuestionThe next gap, highlighted.
answerQuestionActs. Enters one approved answer. Requires an approval id.
showQuestionActs. Scrolls a question into view and highlights it.
reviewerEditsWhat the human changed by hand, with before and after. Excludes the extension's own writes.
probePortalWorks out how an unfamiliar portal is built. Looks; does not click.