The agent10 of 15
Reports
On this page
One tool, make_report, in the report toolset.
It fills a fixed HTML template with content the model supplies. She never writes HTML or CSS — the layout is not hers to choose.
Offered in both modes. The schema's own rules decide when to call it, not the mode gate.
When it should be called
The schema is unusually restrictive, and on purpose:
"OPTIONAL end-of-work report. Use it ONLY when ALL of these hold: (1) the task is genuinely DONE (everything actually executed and verified — never before the work, never mid-task), and (2) it was a LONG, multi-part job whose outcome is worth a written summary the user will revisit … For a short or simple task (a couple of steps, a quick lookup, one file) do NOT make a report."
One exception: if you explicitly ask for a report, a downloadable, or a PDF write-up of a substantial job, that is exactly what it is for.
Calling it twice is refused. If a report with the same title was just made in this session, the second call is a no-op — "I already put together '…' — it's saved in your Files." Before that guard, a reflexive second call produced two files and two memory notes.
What you get
Takes: title, summary, and optional steps, results, files, next_steps, sources.
Three things happen on success:
- The viewer opens — the filled HTML is held in memory for this session and rendered in the frontend's iframe, with a one-click PDF export.
- An
.htmlfile is written to your Files atreports/<slug>-<YYYY-MM-DD>.html, and anartifactframe announces it. - A memory note is appended under the
reportstopic: "Produced a work report titled '…'; saved in Files."
The in-memory viewer copy and the PDF export are gone when the process restarts. The .html file
in your workspace is not.
The sources rule
This is the part worth knowing about, because it is the one place the tool refuses a call outright.
If the report's own text advertises citations and it has none, the call is refused. Nothing is produced, nothing opened, nothing saved:
"I did NOT make that report — its text promises sources it hasn't got. Nothing was produced, nothing opened, nothing saved … Call make_report again either WITH
sources… or with that claim removed from the text. Never write a URL you didn't see."
Before that refusal existed, the schema had no sources field at all and every report promised links
it could not hold.
Sources are backfilled
You do not have to lose a real citation to a forgetful model. If sources is empty, the tool falls
back to the URLs this run actually surfaced — collected from search annotations, from pages she
opened, and from links she showed you. Only real ones; nothing is reconstructed.
The refusal is narrow, and witnessed
Narrow, because judging the whole text refused five ordinary reports in a row — about menus, about broken pages — each asking her to delete a true sentence. A bare "with the links" is what any job about a website says about a footer. So a link promise counts only when it is about the deliverable, decided by the two words immediately before the promise. Reading the sentence as a whole keyed on the word informe, which opens every Spanish report summary ever written.
Witnessed, because a refusal is a non-empty string, and the loop scored a green tick for no report at all until the refusal registered itself as one.
"I've opened it for you" needs a witness too
The report_ready frame is dropped when nothing is listening, so the two halves — the frame and the
sentence about it — can separate.
The tool asks events.draws_cards(session_id): not "did the frame reach anyone" but "is there a
surface that paints a viewer". A Discord session consumes frames and paints no viewer, and that is a
different answer.
Three endings, and the tool returns a different instruction for each:
| What she is told | |
|---|---|
| Viewer present | "It's in front of them now — a viewer on a screen, a numbered row in a terminal — so do not describe how it opened." |
| No viewer, file saved | "It did NOT open on screen (no viewer is connected), so do not tell the user it's open — tell them where it's saved instead." |
| No viewer, no file | "…and it could not be saved to their Files either — say so plainly; there is nothing to point them at." |
Where reports belong
Work mode carries an explicit filing rule:
- research findings →
research/(the research skill handles this) - finished-work reports →
reports/(this tool saves there automatically) - screenshots →
screenshots/<source>/, filed automatically - a multi-file project → its own folder
- throwaway files →
$TMPDIR, which is~/.kotoba/tmpand never appears in your Files
For a research task the order is: save the findings file first, then report on it.
