Architecture & Responsibilities
PDF Agent Stack is built as independent MCPs × Skill orchestration. Each MCP is self-contained with no dependency on the others; orchestrating multiple servers (procedure and knowledge) is the Skills' job.
The whole picture
Shapes indicate the kind of each element (→ shape legend).
An agent may call the MCPs directly, or leave the orchestration to a Skill. With the Skills installed, the call order, how to read the verdicts, and the report format are all fixed for you.
There are only two external dependencies: pdf-spec needs the corpus of specification PDFs (not bundled, as they may not be redistributed), and pdf-verify delegates PDF/A and PDF/UA verdicts to veraPDF. The reader and the writer depend on nothing outside themselves.
The four-layer model — which Skill calls which MCP
| Layer | Server | Returns | Never does |
|---|---|---|---|
| Canon | pdf-spec | Clauses and requirements (shall/should/may) | Never opens the PDF under examination (it reads only its own spec corpus). Never judges conformance |
| Substance | pdf-reader | Observations (text, structure, signature fields) | Never says pass/fail. No cryptographic verification |
| Authenticity & conformance | pdf-verify | Verdicts (signatures, tampering, PDF/A, PDF/UA, 4-value policy) | Never proves the file meets the standard — it can only find where it breaks the rules |
| Creation | pdf-writer | New and edited PDFs | Never signs. Can write a label but cannot make the file meet the standard |
The boundary rule (one line)
If it returns compliant / valid / pass-fail against an ISO standard, it belongs to verify; if it only returns observations, it belongs to reader.
Declaration, conformance, validation
This distinction runs through the whole of PDF Agent Stack.
- Declaration — A label the file wrote about itself. "I am PDF/A" in the metadata. Writing it is not evidence
- Conformance — Whether the file actually meets the standard. There is no way to prove it in full; you can only find where it breaks the rules
- Validation — What a validator (veraPDF and the like) reports against the checks it implements. A pass means "this inspection did not fail", not "the file conforms to the standard"
That is why the writer's ensure_pdfa is a tool that writes a label, and the rule across PDF Agent Stack is: whatever you label, you measure with verify's validate_conformance.
A validator's output is a verdict, not evidence
Outside writing on this subject sometimes lists "validator output" and "signature verification" as examples of evidence — of what was seen. PDF Agent Stack keeps the two apart.
| Who produces it | Example | |
|---|---|---|
| Observation (evidence) | reader | XMP carries a pdfaid declaration. Two incremental updates are present. No revocation information is embedded in the document |
| Verdict | verify | use_with_caution, fired by POL-CAUTION-REVOCATION-UNKNOWN |
A veraPDF result is not an observation either. "veraPDF reported no violation under this profile" is the observation; turning it into a value against an acceptance profile is what evaluate_policy does.
These three lines say different things. Collapse them and only the last survives.
- Observation: XMP declares PDF/A and veraPDF reported no violation under that profile
- Verdict: this inspection did not fail (
use_with_caution; whatever the checks do not cover was not measured) - Wrong summary: the file conforms to PDF/A
What disappears when four values are collapsed into three
evaluate_policy returns four values. Mapping them onto yes / no / unknown loses two rows.
| Four values | Collapsed to three | What is lost |
|---|---|---|
trust_and_use | yes | — |
use_with_caution | yes | The use restriction. "Usable with caveats" becomes "usable as is" |
human_review_required | unknown | The difference between "no evidence" and "unwritable criteria". The latter stops reaching a human |
reject | no | — |
The third row is the point. human_review_required covers both "a fact needed for judgment is missing" and "the criteria cannot be written". Collapsed into a single unknown, the latter is filed as something that more evidence would resolve, and never reaches review. Four values cannot be recovered from three.
Incoming and produced PDFs both go through verify
Two of the three inputs in the diagram above (an incoming PDF, a PDF to produce) end with a verdict from pdf-verify.
| Input | Skill | Flow | On reject |
|---|---|---|---|
| Incoming PDF | pdf-trust | audit → four-value verdict → use / archive | Not used. The reason goes into the Trust Report |
| PDF to produce | pdf-publish | write → read-back → verify (quality gate) → delivery | Not delivered. The reason goes into the Publish Report |
The third input — a PDF you only want to read — does not go through verify. pdf-read picks how to read it and writes what was read and what could not be into a Read Report. It decides neither whether to accept nor whether to deliver, so no verdict from verify is needed.
The four-value verdict (trust_and_use / use_with_caution / human_review_required / reject) is returned by evaluate_policy's rule engine. It is deterministic: the same input always gives the same result. The LLM writes only the explanation of that verdict and the recommended actions; it does not change the verdict.
Assertion strength (T1/T2/T3)
How strongly a verification result may be stated depends on whether the normative text is at hand.
| Tier | Standard | How strongly you may speak |
|---|---|---|
| T1 | ISO 32000-1/-2, ISO 14289 (PDF/UA) | Quote the clause and state it plainly |
| T2 | ISO 19005 (PDF/A) | Say only "veraPDF judged this COMPLIANT" |
| T3 | ETSI PAdES | Report a structural observation — "structure matching B-LT" — never "conforms" |
The prose on this site follows the same rule.