Skip to main content
A briefing request looks simple from the teacher’s side — fill in a topic, maybe a speaker and an organization, submit. What happens between submit and a finished document is a queue, a research fan-out across several angles, a chunked writing discipline, and a save gate that will reject a briefing that isn’t actually usable.
gate rejects → revise
retries
over limit
Queued
Running
heartbeat before every search
Chunked writing
≤1,500 chars/chunk · every 1–2 chunks
Save gates
≥800 chars · ≥3 links · still running
Done
Orphan recovery
no heartbeat > 6 min
Requeue
≤8 attempts · last two simplified
Failed
with an honest note
Gray traces the happy path; terracotta traces the orphan-recovery and retry path; gold marks the save gate — the only place a briefing is judged worth keeping. A row only fails after 8 requeue attempts, the last two already stripped to a simplified, no-further-reading mode.

Queue and dispatch

A submitted request is written to Postgres as status: queued. A cron-driven dispatcher claims queued rows on a schedule, marks the claimed row running, and hands it to the Briefing agent on the durable agent runtime. The web app doesn’t wait around for the agent to finish — it dispatches and moves on; completion is observed later, either by the agent’s own save call marking the row done, or by the same heartbeat-aware recovery that watches course production.

Research, fanned out across angles

The agent researches a fixed set of angles, skipping any whose input field is empty:
  1. Domain crash course — what this field is, explained plainly, and its core concepts.
  2. Institution profile — background, reputation, and recent moves of the host organization.
  3. Speaker profile — recent public statements and notable positions.
  4. Controversies and hot topics — what practitioners are debating recently, anchored to a date the dispatcher injects mechanically so the agent can’t misjudge “recent” by guessing the wrong year.
  5. Bilingual term table — the heaviest angle by design, and the interpreter’s core asset from the briefing. The agent actively searches authoritative bilingual sources (government white papers, Ministry of Foreign Affairs bilingual transcripts, UN parallel texts) for each concept, and grades every rendering official or reference depending on whether it actually found a citable bilingual source — never upgraded on confidence alone.
  6. Further reading — three to eight entries, every one a real, working link the agent actually fetched or searched to, never a placeholder.
This loosely follows Setton & Dawrant’s account of what an interpreter needs before a real assignment: domain-specific knowledge (what the field is) and encounter-specific knowledge (who’s hosting, who’s speaking, what’s contested right now).

Writing in chunks, not one shot

The agent doesn’t compose the whole document in memory and hand it over in a single write. It appends the briefing to a sandbox file in chunks — roughly 1,500 characters at a time — and reports progress after every chunk or two. This exists because writing a multi-thousand-character document in one model turn, with no intermediate signal, looks identical from the outside to a stalled agent: nothing observable happens for minutes at a time. Chunked writing turns “no visible progress for ten minutes” into “a heartbeat every thirty seconds,” which is what makes it possible to tell a slow-but-alive agent apart from a dead one.

The save gate

When the file is complete, the agent calls a save tool that reads the finished file and applies gates before it’s allowed to reach done:
  • A minimum length — a briefing under roughly 800 characters is judged too thin to be useful and rejected rather than saved.
  • A further-reading floor — at least three real, clickable links, or the save is rejected. A briefing with zero further reading fails this gate outright; the normal mode always requires it (a simplified fallback mode, used only after repeated retries, is explicitly exempt and says so in the document itself).
  • A running-status write guard — the save only succeeds if the row is still running when it commits. This exists specifically to stop an old, previously-orphaned session from overwriting a briefing that a newer retry already finished (see Truth Layer for why that guard was added).
A rejected save isn’t final — the agent reads the reason, edits the file, and resubmits within the same session.

Heartbeat and self-healing

A briefing row is heartbeat-aware, not wall-clock-timed from when it started: as long as the agent keeps updating progress, the row is never reclaimed as orphaned, no matter how long real research and writing takes. Only once progress goes quiet past a threshold does the row get requeued. Retries are capped; the last two attempts before the cap switch to a simplified mode — two core angles only, no further-reading requirement — that trades completeness for a real chance of finishing rather than exhausting the retry budget chasing a full result.