Serhii Zabolotnii
← All posts
AIagentsTRACEknowledge graphpress officeClaude Codeverification

A press-office assistant that knows the date: the TRACE architecture for texts written in an official's name

How to build an AI assistant for a press office in which the plausible error — an outdated title, a superseded institution name, an invented figure — is stopped by code rather than by a request in the prompt: a temporal knowledge graph in git, an independent fact check, escalation as a normative document, and a human without whom no text is approved.

The most dangerous error in an official’s post is not an illiterate one but a plausible one. This article is about splitting an AI press-office assistant across the four layers of TRACE so that such errors are stopped by code, not by a polite request in the prompt.


The error nobody notices — except everyone

Picture an ordinary morning in a press office. A post has to go out in the principal’s name: thank the partners, mention two officials, name an institution, give one figure. A language model will write it in twenty seconds, and the text will read smoothly.

Now suppose one of those officials moved to a different role a week ago. The institution was renamed six months ago, and the old name still appears in half of the archived posts. The figure is correct, but it is last year’s. None of these errors looks like an error. They slip past a tired editor and become visible only when readers notice them, which means all of them at once.

The usual answer is “let’s add RAG”. But a vector store returns the most similar passage, not the one that was valid on the publication date. To it, “head of department” from three years of posts and “head of department” from last week are almost the same vector. “Who held which role on the date of the post” is a question about time, not about similarity.

I designed and built a pilot of such an assistant for an official’s press office. What follows is the architecture, not the story of a particular client: I deliberately leave out the name, the channel and the institution. What interests me is what carries over to any press office.


What the system does and what it does not

The boundaries came first, because everything else depends on them.

It does: draft a post in the principal’s style from a short brief; check every name, title, institution name, number and date in the draft against a temporal knowledge graph; flag whatever it could not verify; keep a log of who approved the text and when; and, once the text is approved, write the post and its claims back into the graph.

It does not: publish. The system has no publishing tool at all, and the network of the working environment does not reach the messenger. A person copies the approved text and publishes it. Nor does the agent formulate first-person positions, assessments or promises on its own initiative: the system detects such sentences and sends them to management for sign-off.

This is not a limitation of the pilot but a principle: the agent is a tool of the press office, not a substitute for the principal’s position.

The life cycle of a draft: from brief to approval; the knowledge graph is read at every step and grows with each approved post


Why TRACE

TRACE is an engineering framework for agentic systems in operationally critical domains. Its framework paper (arXiv:2605.03838) combines a four-layer reference architecture with an explicit split between classical ML and LLM validators, a set of trust metrics grounded in the metrological standards GUM, VIM and ISO/IEC 17025, and a principle of model parsimony. The key idea: using a large language model is a deliberate design decision, not the architectural default.

Before the press office, the framework went through several domains, and each contributed something that was needed here.

  • Clinical decision support (arXiv:2604.26671). The first instance: a deterministic clinical core, an assistant that validates the context of a specific patient, tiered model escalation, and the physician as the final reviewer. From there come selective verification of exactly the critical claims and a bounded, dated context.
  • An industrial multi-domain platform for upstream oil and gas. The same layering across three sub-domains (technology, operations, administration) showed that the dominant layer shifts with the type of evidence. For sensor signals, classical ML carries most of the load; for rules and texts, it is the deterministic core plus LLM validators. A press office is a case of the second kind. The deterministic core of this line can be inspected live: the drilling gate demo on open Utah FORGE data, built on the principle “un-assessed ≠ pass”.
  • Judicial analytics (Zenodo, 10.5281/zenodo.22128390). An AI assistant for the Supreme Court of Ukraine’s portal of legal positions: a model drafts a legal position from the text of a decision, and an authorised court officer approves it. This is the closest relative of the press office. There too, the model writes the draft and a person signs it. There too, layer L3 is treated as a normative document, managed without developers.
  • Institutional systems in general (AIID-2026, 10.5281/zenodo.22917150). The thesis of TRACE as a distribution of cognitive load between AI layers and people. The “one language model for everything” approach breeds automation bias and an unpredictable load on operators. Meaningful human oversight is measured by the review burden index and the override rate.
  • Runtime Assurance Contracts (arXiv:2609.39717, code, Zenodo). A formal schema under which a failed or un-assessed mandatory check forces the agent to retry, escalate, defer or stop. An aggregate score cannot authorise an action. Hence the rule on which approving a post rests: green checks do not compensate for a single red one.
  • A research agent for a scientific school (blog). The same logic in science: every number in a manuscript has a chain of evidence back to an artifact on disk, and the agent does not take its own word for it.

A press office looks like an easier domain: nobody dies of a clumsy post. But the structure of the risk is the same. There is the public accountability of a specific person, there is a plausible error that is expensive to retract, and there is the temptation to trust a smooth text. What is new in this instance is time. In the earlier domains, the context is mostly physical or normative. Here it is biographical: who held which role, and what the institution was called, on the exact date of the text.

TRACE splits a system into four layers:

LayerIn TRACEIn the press office
L1 — deterministic corerules, protocols, reference standardsthe temporal graph, “title on a date” queries, channel-rule and stop-list checks, the approval script
L2a — classical MLcalibrated classifiers with a bounded outputempty, by design (see below)
L2b — LLM componentsgeneration and validation where language understanding is genuinely neededthe draft author; an independent fact checker; claim extraction from the archive
L3 — tiered orchestrationescalation policy, states, retriesescalation rules as a normative document of the press office; the draft life cycle
L4 — bounded human supervisionaccountability, the right to overridethe press secretary, the head of the press office, the principal; the approval log

TRACE layers and the components of the press-office assistant: L2a is deliberately empty

Below is what sits in each layer, and why.


L1. A knowledge graph that knows the date

The heart of the system is a temporal knowledge graph. It has two layers.

The canon is maintained by a person. It holds people, roles, institutions, places and topics. Every role is an edge with the dates valid_from and valid_to. Every institution has a history of names with their periods. An old name does not disappear; it becomes an alias with the date up to which it was valid.

The episodes are the posts and the claims extracted from them. They were extracted from several years of the channel archive: each claim has a type (fact, promise, official position, assessment), the event date if it is known, and a verbatim quote from the post. Code checks that the quote matches a fragment of the text character for character. A claim that is not in the text is rejected before it reaches the graph.

Three decisions turned out to matter more than they seemed at the start.

“The graph does not know” is not “the graph contradicts”. Many roles are known only from the channel itself: the first and the last mention, not the dates of appointment and dismissal. Such bounds are marked precision: attested. If the publication date falls outside them, the check does not say “error”; it says “the graph does not know this, please verify”. The difference between a contradiction and an unknown is what separates a useful check from an irritating one. Without it, the system either stays silent or shouts at every name. It is the same principle as in the drilling gate: un-assessed is a state of its own, not a silent “pass”.

An illustrative example: an exact role boundary, a bound known only from mentions, and an institution's renaming yield different verdicts on the date of the post

The graph is append-only. Correcting a fact means adding a new claim and a SUPERSEDES edge to the old one, not editing. The graph is stored as text files in git (YAML for the canon, JSONL for the episodes), so the commit history provides the recording time. The state of knowledge at any moment can be restored from git. This is bitemporality on the cheap: “when it was true” lives in the edges, “when we learned it” lives in git.

Search by lemmas, not by strings. Ukrainian inflects names and titles. “Petrenka”, “Petrenkovi” and “Petrenkom” are one person, and search has to know that. So the index is built on sets of lemmas (pymorphy3 with a Ukrainian dictionary), and the canon’s aliases are expanded into the query automatically.

The index is SQLite with full-text search. It is derived: it is not committed and is rebuilt by a script in a few seconds at the start of every session. There is no database server and no vector database.

L1 also holds the deterministic checks of the draft: the channel’s length limits, the stop list (wartime data blocks approval; calques and bureaucratese are only flagged), and roles and institution names on the publication date. If a role’s boundary is exact and the date lies beyond it, that is an error. If the boundary is attested or there is no record, it is a warning.


L2a is empty. That is a decision, not an omission

The sixth principle of TRACE is model parsimony: the type of learned component is chosen by the task, not by the habit of reaching for an LLM. It comes with a metric, CPR: the ratio of the cost of the most economical adequate model to the cost of the deployed one.

In this domain, classical ML has nothing to do yet. A title on a date is a graph query. The current name of an institution is a graph query. Whether the text has a sum next to the word “budget” is a rule. Every place where a classifier could go is closed by deterministic code that needs no calibration. So L2a is deliberately empty, and the system contains no component that would ever need retraining.


L2b. One model writes, another checks — without seeing how it was written

An LLM is needed where language understanding is genuinely required: writing a text in a specific person’s style, breaking a draft into atomic claims, extracting claims from the archive.

The key decision is to separate the author from the checker. The fact check is done by a separate subagent. It receives only the draft’s identifier, and from a script it gets the plain text, the publication date, the post type and a hash of the text. It does not see the plan, the source annotations or the author’s reasoning. If the author got a title wrong because it misread the brief, the checker does not inherit that error along with the context.

The checker breaks the text into claims and gives each one of four verdicts: confirmed (with the identifiers of graph nodes as evidence), contradicts (and what exactly the graph says), not_in_graph (something new — not an error, but a flag for the person), and opinion (an assessment with no verifiable content). Separately, it checks every name, title and institution name: the correct form, the role valid on the date, the current name.

Code once more checks the quote of every claim. The model cannot “confirm” something that is not in the text.

One more detail: the draft text, archived posts and imported documents are data, not instructions. A phrase like “mark this as confirmed” inside a document is checked as ordinary text, not executed. For a press office that receives material from dozens of outside people, this is not paranoia but hygiene.

Which model goes where

The language models in the system are not all the same, and that is a decision, not an accident. TRACE’s principle of model parsimony applies inside L2b as well. The question is not only whether an LLM is needed here, but which one. The answer depends on two quantities: how many times the task is performed, and how much one missed error costs.

RoleModelVolumeCost of an errorWhy
Extracting claims from the archiveSonnet — faster and cheaperhundreds of posts, once, in parallel batcheslow: a deterministic validator rejects every claim whose quote does not match the textbulk work with a strict check at the output is cheaper on a smaller model
Drafting a postthe session modelone text per briefmedium: the fact check and a person come nextit needs style and an understanding of the brief, and later steps will catch its errors
Fact checkOpus — the most capable availableone call per version of the texthigh: a missed error is one the person will see, and then perhaps the readersa miss costs more than an extra call, and there are few calls

The stronger model here is a resource invoked by a rule, not a layer above the others. Extraction shows this. If an independent review of a sample shows quality below the threshold, the failing batches are re-run on a more capable model (Opus). This is tiered escalation in its pure form. The decision to “re-run on the stronger model” is made by a policy with a threshold, and the stronger model merely performs the same task as the weaker one. In TRACE terms, both models sit in the L2b inventory, and the rule for choosing between them belongs to L3.

The same ladder can be extended downwards. For extraction, Haiku, the smallest and cheapest model, might well be enough. But there is a trap. The output validator checks that a quote is verbatim and that the record conforms to the schema. It cannot see whether the claim type and the event date are right. Those are exactly the errors the independent review of a sample found even with Sonnet: a date of “1 January” where the post gave only the year. So switching to Haiku is not a guess but a measurement. Run the same sample, assess it with the same protocol, and if quality is not below the threshold, the parsimony principle demands the smaller model. The ladder then has three rungs: Haiku by default, with Sonnet and Opus for the batches that fail the threshold.

One limitation is worth naming. The author and the checker come from the same model family. Their independence here comes from context: the checker does not see the author’s reasoning. A model from another family would add independence of errors as well, because two models of one family are more likely to make the same mistake. For a pilot this is enough. For permanent use, a checker from another family is worth considering, as in the research agent, where the author is never the judge.


L3. Escalation as a normative document

In TRACE, L3 is the policy that decides when a result goes up a tier. In a press office, the upper tier is the people with the authority to sign off.

The escalation rules are written not as configuration in code but as a normative document of the press office: a human-readable text plus one machine-readable YAML block with a version and the fields “approved by” and “approved at”. Code reads the block, and the head of the press office changes it through a dedicated skill with an explicit confirmation. A change of tone or of the escalation rules is a person’s dated decision, not a developer’s commit.

Four kinds of sentences require management sign-off:

  1. a new first-person promise;
  2. an official position on a public issue;
  3. budget figures — a sum next to words such as “budget”, “estimate” or “funding” in the same sentence;
  4. a first-person assessment.

Escalation is determined twice and independently: deterministically from the text (trigger lemmas, post type, numbers with currency units) and from the claim types the fact checker found. Agreement between the two channels adds reliability; disagreement is a signal for the person.

The draft life cycle also belongs to L3: planned → drafted → checked → approved | rejected. Only a script moves a draft between states.

The weakest point: the session’s language model does part of L3’s job. In canonical TRACE, L3 is a stateful policy over the L2 inventory, not a language model. An approach in which an LLM orchestrator runs a hierarchy of LLM agents conflates the choice of model class with the policy for invoking it (arXiv:2605.03838). This system does not separate them completely. The model of the Claude Code cloud session picks the skill from the operator’s message and decides when to call the subagents. Those decisions are probabilistic. So everything that must be guaranteed has been taken out of its hands. A script moves drafts between states, escalation is set by the rules of the normative document, approval requires three mandatory conditions, and a hook will not let a turn end with an unchecked draft. The model can pick the wrong route, but it cannot bypass these conditions. Its routing errors are measured by a dedicated test. The session model is not pinned in the settings, so the test has to be re-run after every model update: a new model may read the same skill descriptions differently.


L4. A person without whom no text is approved

Only a script can approve a draft, and only under three conditions. All three are mandatory and do not compensate for one another, exactly as formulated in Runtime Assurance Contracts:

  • the fact check matches the current text. The check result is bound to the SHA-256 of the text. Change a comma after the check, and the check has to be repeated;
  • the rules are passed, and every contradiction with the graph is closed with a stated reason;
  • the sign-off is recorded if escalation was triggered: who, when and through which channel.

Three mandatory conditions for approval: one red check stops it, and green checks do not compensate

After approval, the post and its claims go into the graph as new episodes marked “verified by a human”. The loop closes: the next draft will be checked against this text as well.

There is an honest limitation worth naming here. In the pilot, one operator works with the system from one account. The terms of service forbid sharing an account, and a team plan is not available yet. So the operator records management’s sign-off on their word. The log captures an attested sign-off, not a signed one, and the messenger message remains a second source. For a pilot, this is acceptable. For permanent use it is not: everyone who signs off should work from their own account.


Guarantees live in code, not in the prompt

The most important principle of the whole system: an instruction to the model is a wish; a hook or a script is a guarantee. So I spelled out separately what in the system is probabilistic and what is not.

WhatMechanismGuarantee
Choosing the right skill from the operator’s messagea skill description with trigger phrasesprobabilistic; measured by the routing test
Building the index and self-checka session-start hookdeterministic
Direct edits to graph data or rewriting git historyblocked by a hookdeterministic
Ending a turn with an unchecked drafta hook prevents itdeterministic
The “approved” statusonly a script, only under the conditions abovedeterministic
Writing to the loga commit and push after every changedeterministic
Publishingthere is no tool, and the network does not allow itdeterministic

Where the model stays probabilistic, there is a safeguard. Skills that change data (graph facts or norms) first show the change and wait for an explicit “yes”. A wrongly triggered skill breaks nothing; it only asks an unnecessary question.


The interface is a phone

A press secretary does not sit at a terminal. So the interface is a Claude Code cloud session on a private repository, opened from a phone. The operator types or dictates the task in plain language: “prepare a post about…”, “check the facts”, “add to the graph that…”.

Two architectural decisions follow. First, all the logic — skills, subagents, hooks — lives in the repository itself, not in a plugin, because plugins are not installed in cloud sessions. Second, every change to a draft, the graph or the norms is a separate commit that is pushed immediately, because the cloud session’s virtual machine can disappear together with any unsaved work.

The repository is the code, the knowledge base and the accountability log all at once. That makes audit simple: everything that happened is in git log.


How to measure it

The metrological side of TRACE requires every quality property to be specified and measured before launch, with the thresholds agreed with the client in advance rather than fitted afterwards.

The right-hand column gives the closest TRACE metric, not an identity: the pilot’s metrics are counted per post, TRACE’s per layer.

Pilot metricThresholdClosest TRACE metric
Critical errors in approved text (name, title, institution name, figure, date)0ETC — evidence trail completeness
Share of a draft’s critical errors flagged by the check before a person sees it≥ 90 %CFI — context freshness index
Share of drafts a person discarded and rewrote from scratch≤ 15 %OvR — override rate
Blind test: can the press secretary tell real posts from drafts≤ 65 %—
Time from brief to finished text, versus writing by hand−40 %RBI — review burden index

A note on OvR. A very low override rate is not necessarily good news: it may mean the person has stopped reading. So it is read together with the blind test and the review of edits, not on its own. I have written separately about automation bias as the main risk of institutional systems (AIID-2026), and about why trust has to be measured rather than felt in an earlier post.

Where things honestly stand today. The system is built, an end-to-end local run has passed, the graph has been extracted from the archive, and the canon has been approved. The routing test sent 64 of 64 messages to the right skill, with no false calls to the skills that change data. But that set is synthetic: it tests the interface, not usefulness. The pilot with real posts is still ahead, and there are no figures yet that could honestly be called effectiveness. I will write about them when they exist.


What carries over to another press office

Almost everything. For a different principal, the canon (people, roles, institutions), the norms (style profile, stop list, escalation rules) and the channel rules change. The core — the graph, the check, the approval, the hooks — stays the same. Facebook, LinkedIn or Viber are added as adapters with their own channel rules, without changes to the core.

The main lesson reaches beyond the press office. The model provides speed, but trust comes from the architecture: a deterministic core that knows the date; an independent check that does not see the author’s reasoning; escalation rules written by a person; and a person without whose signature a text does not become a text.


References

  1. Zabolotnii S. TRACE: A Metrologically-Grounded Engineering Framework for Trustworthy Agentic AI Systems in Operationally Critical Domains. arXiv:2605.03838, 2026. https://arxiv.org/abs/2605.03838
  2. Zabolotnii S., Holinko V., Antonenko O. From Black-Box Confidence to Measurable Trust in Clinical AI: A Framework for Evidence, Supervision, and Staged Autonomy. arXiv:2604.26671, 2026. https://arxiv.org/abs/2604.26671
  3. Zabolotnii S., Babanly R., Pavlenko Yu., Lytvynenko I. From a Court Decision to a Legal Position: Automation of Legal Analysis by Means of Artificial Intelligence in the Practice of the Supreme Court (in Ukrainian). Preprint, Zenodo, 2026. https://doi.org/10.5281/zenodo.22128390
  4. Zabolotnii S. TRACE: Architectural Decomposition of Cognitive Load in Institutional AI Systems (in Ukrainian). AIID-2026, Odesa, 2026, pp. 9–12. https://doi.org/10.5281/zenodo.22917150
  5. Zabolotnii S. Trust Is Not a Score: Runtime Assurance Contracts for High-Risk AI Agents. arXiv:2609.39717, 2026. https://arxiv.org/abs/2609.39717 · code: https://github.com/SZabolotnii/TRACE-RAC-code-supplement · https://doi.org/10.5281/zenodo.23410711
  6. TRACE drilling gate demo on open Utah FORGE 58-32 data. https://drill-ai-gate.traces.solutions
  7. Zabolotnii S. An agent that doesn’t take its own word for it: how I built a research framework for a scientific school on top of AutoSci. Blog, 2026. https://blog.szabolotnii.site/posts/autosci-research-framework/
  8. Zabolotnii S. If You Can’t Measure Trust in AI — It Doesn’t Exist. Blog, 2026. https://blog.szabolotnii.site/posts/trust-in-ai-part7/

TRACE: traces.solutions.