Imperal Docs
Core Concepts

Fact-ledger — verbatim cross-turn recall

Fact-ledger — verbatim cross-turn recall of exact tool results across the last 5 turns, no extension API; the anti-fabrication surface under the classifier.

The essence

The fact-ledger is the platform's verbatim cross-turn recall surface. It stores the exact JSON-serialised ActionResult.data returned by every successful tool call and replays the most recent five turns of those facts to the intent classifier on every subsequent chat turn. Your extension writes nothing to the fact-ledger directly — the platform populates it automatically after each successful tool call. There is no fact-ledger decorator and no fact-ledger accessor on the context object. Your only contract is to return clean, structured data inside ActionResult.data, and the platform takes care of the rest.

Do not use the fact-ledger as persistent state — it is bounded to the last five turns; use ctx.store for longer-lived data. Do not rely on ActionResult.summary as the recall surface — the platform records .data (the structured payload), not the human-readable prose summary.

Why it exists

Without verbatim recall, an agent answering a follow-up turn has only the prose summaries of earlier turns to work from — and prose paraphrases away exact facts. A list_tasks call returns 36 tasks; a naive follow-up turn announces "you have 50 tasks", filling in a plausible-but-wrong number because the precise count was no longer in front of it.

The fact-ledger closes that gap: it preserves the exact structured data your tool returned for the last few turns, so the agent always has the real numbers, IDs, and addresses to ground its answers — never a paraphrase it might get wrong.

What it stores

After every successful tool call, the platform records a compact entry for that turn capturing the verbatim structured payload your tool returned:

FieldSourcePurpose
AppThe extension owning the toolLets the agent attribute a fact to its source extension
ToolThe @chat.function name that ranIdentifies the specific tool that produced the data
DataThe JSON-serialised ActionResult.dataThe verbatim payload the agent later sees

On every chat turn, the platform surfaces these FACTS: lines for the most recent five turns directly under each turn's prose preview.

Caps and limits

The fact-ledger is bounded so it stays affordable even when the agent runs on every chat turn.

ConstraintValue
Aggregate fact-ledger size per turn≤ 3000 chars
Number of turns retained in the agent's viewLast 5
PII handlingSensitive values are masked before the agent sees them by default
Verbatim contractThe platform records the structured ActionResult.data, not the prose summary
Deep serialisationNested structures are preserved at full depth — no shallow projections

When a turn's facts exceed the aggregate cap, the platform truncates from the tail (the oldest tool calls in the turn) and surfaces a warning marker. Truncation is rare in practice — typical tool calls produce 100-500 character payloads.

PII handling

When a tool returns sensitive content (an email body, a customer name, a phone number), the platform masks email-shaped, phone-shaped, and named-entity strings before the agent ever sees them. PII is masked by default — your structured data is recorded faithfully, but the recall surface the agent reads is redacted.

What the agent remembers

For each recent turn, the agent has both a short prose preview and the verbatim structured facts your tool returned that turn.

What this shows: a two-turn exchange where the second turn's anaphoric reference ("отправь на тот же") is resolvable because the first turn's structured email address was preserved verbatim.

  • Turn 1 — user: "показать письма за сегодня". Your list_inbox tool returns data containing {"unread": 8, "messages": [{"id": "abc", "from": "sarah@example.com", "subject": "Q3 plan"}]}. The platform records that structured payload verbatim.
  • Turn 2 — user: "отправь на тот же адрес «статус по проекту»".

In the second turn, the agent resolves "тот же адрес" by reading the previous turn's recorded facts and extracting sarah@example.com verbatim from the structured data.messages[0].from field — never from the prose summary, which might have paraphrased the address away.

What you DO NOT do

The fact-ledger has no extension API. Specifically:

  • There is no fact-ledger decorator. Attempts to import one fail at module load.
  • The context object exposes no fact-ledger accessor — reading one back returns nothing.
  • The skeleton has no writer method on the context object either — both the skeleton and the fact-ledger are read-only from extension code; the platform is the sole writer to both.

Your only contract: return clean structured payloads in ActionResult.data.

  • If you put 30 KB of nested JSON into .data, the platform truncates per the aggregate cap (3000 chars per turn) and the agent sees only the leading portion.
  • If you put PII in plaintext, the platform masks it before the agent sees it.
  • If you put unstructured prose in .data (a string instead of a dict), the agent cannot index into fields — anaphora resolution will fail.

Federal invariants

The fact-ledger is defended by platform-enforced guarantees you can rely on:

📊

Verbatim, not paraphrased

The platform records your [ActionResult](/en/reference/glossary/).data exactly — never the prose summary.

🧬

Full-depth preservation

Nested structures are kept at full depth — no shallow projections that lose fields.

📏

Bounded per turn

≤3000 chars aggregate per turn; the oldest tool calls in a turn are truncated first when exceeded.

🔐

PII masked by default

Sensitive values are masked before the agent ever sees them.

🧠

Always replayed

Recent facts are always made available to the agent under each turn's preview, every turn.

See the federal invariants page for the full inventory.

What's next

On this page