Documents

Build a report from agent work

Try it

Turn aggregated findings — news, monitoring, research — into a report someone will actually read: a chat digest, a Markdown doc, or a self-contained HTML dashboard. Use when a task ends with a pile of data and the risk that nobody reads the writeup.

What it does

Turning aggregated findings into a report people read

The skill document

Turning aggregated findings into a report people read

Collecting the data is the easy half. A report nobody reads is worth less than no report at all — it teaches whoever assigned it that they don't need to check the next one either. What follows is what decides whether the second one gets read.

Before writing anything: what actually changed

The single biggest failure mode of a recurring report is repeating what's stable and burying what's new inside it. Before drafting:

  • Diff against the last version, not the raw source. If a section hasn't changed, say "unchanged" in one line — do not re-describe it at the same length as something new.
  • Sort by what the reader needs to act on, not by source or chronology. A reader skims top to bottom once; the first three lines are the only ones guaranteed to be read.
  • If there's nothing worth reporting, say that in one line. A padded report trains the reader to skim past all of them, including the ones that matter.

Pick the format for where it's read, not for what looks impressive

Three shapes, in order of how often each is actually the right one:

  1. A chat message. Five to seven lines, plain text, one clear point per line. Correct for anything read on a phone between other things — which is most recurring reports. Do not reach for HTML because it exists.
  2. A Markdown document. For something that needs headings, a table, or links, and will be opened deliberately rather than glanced at — a weekly roundup, a comparison. Still short: a table beats three paragraphs describing the same numbers.
  3. A self-contained HTML page. Only when something genuinely benefits from layout — several data series, or something meant to be shared as a link. Single file, inline CSS, no external requests: a page that depends on a CDN being reachable is a page that's sometimes blank. Template below.

Reaching for the fanciest format by default is the second most common failure, right after skipping the diff.

Every claim needs a source, in the report itself

Not "sources available on request" — the specific link or file sits next to the specific line. A number with nowhere it came from is not a finding, it's a guess wearing a finding's clothes. If a source can't be reached, say the section is thin rather than filling it with something plausible-sounding.

Separate what happened from what you make of it

The two are different kinds of claim and erode trust differently if mixed: "the API raised its price 40%" is a fact; "they're betting nobody re-benchmarks" is a read on it. Label the second explicitly — a reader who can't tell which is which stops trusting either.

A self-contained HTML dashboard, minimal and dependency-free

<!doctype html>


{{ report title }}


  {{ report title }}
  {{ date }} · covers {{ window, e.g. "last 24h" }}
  
    {{ number }}{{ what it counts }}
  
  
    {{ what happened, one line }}
    {{ source name }}
  
  {{ what stayed the same, one line, not expanded }}


No JS, no charting library, no font import — each is something that can fail silently when the page is opened somewhere without internet, and a dashboard nobody can open is worse than the chat message it replaced.

What goes wrong

The report grows every cycle and gets read less each time. Almost always means the diff-against-last-time step was skipped — stable sections re-described in full instead of collapsed to "unchanged."

A number with no source next to it. The most common way a report stops being trusted. If you can't find where a number came from, cut the number rather than keep it unsourced.

A stat with no unit, or a chart with no axis label. Obvious in the source data, meaningless on the page once separated from it. If a number needs the surrounding sentence to mean anything, put the unit on the number itself.

Opinion presented as if it were the finding. "X is concerning" is not a finding; "X changed by this much, for this reason we could confirm" is. Say which one is being given.

Getting it to the reader

A report that exists only inside the agent's session was never delivered. How this works is engine-specific; the pattern below is Hermes, checked on a running pod rather than read from documentation.

See what you can actually deliver to, first.

hermes send --list

If it answers "no messaging platforms configured", nothing can be delivered yet — a channel has to be connected before any of the rest of this matters. Checking first turns a silent non-delivery into a clear one.

Send the report as the message.

hermes send --to telegram --file /opt/data/workspace/report.md
hermes send --to discord:#ops --subject "[weekly]" --file report.md

Targets are platform, platform:chat_id, or platform:#channel-name. For bot-token platforms this needs neither a model nor a running gateway, so it works from a cron job — which is what a recurring report usually is.

Send a file as an attachment.

hermes send --to telegram "MEDIA:/opt/data/workspace/dashboard.html"

--file reads the message text from a path; MEDIA: in the message attaches the file itself. Mixing these two up sends the raw HTML of your dashboard into the chat as a wall of text.

Keep the file on the persistent disk, not in /tmp. /opt/data survives restarts, and the previous report is what the next one diffs against — the first section of this skill is impossible without somewhere to keep it.

One thing to know before promising a link: on a pod like this there is no public URL for a file you write. The only HTTP surface is the dashboard, and it sits behind authentication. A report that must be shareable as a link needs somewhere else to host it; an attachment is what actually works out of the box.

What this skill doesn't cover

The delivery commands above are Hermes. Other engines have their own way, and this file does not attempt to guess at them — an invented command is worse than an absent one. Find the equivalent of send --list for whatever you are running before designing around delivery.

Scheduling — how the report gets triggered daily or weekly — is also outside this file.

One trap worth naming even though it belongs to scheduling: a report headed "today" is written in the pod's timezone, which is often not the reader's. A daily digest that arrives at 07:00 for the agent and 23:00 the previous day for the person reading it is wrong in a way nobody reports as a bug — they just stop trusting the dates. Set the pod's timezone to the reader's, or put the offset in the report itself.

Related skills

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

Stores durable facts in a categorized, plain-markdown vault on disk, alongside your agent's built-in memory.

by Iván1 installs

Find why your productivity system keeps failing, then apply the smallest fix — capacity math, bottleneck routing, durable local notes.

by Iván1 installs

Read and write Excel workbooks, worksheets, ranges, tables, and charts in OneDrive through Microsoft Graph with managed OAuth.

by byungkyu800 installs42 stars

More from samorodkin

Browse all skills

Deploy a project from a git repository onto AgentsPodium: frontend and backend on one pod, behind one domain, with a persistent disk. Use when you are asked to ship an app somewhere, or to move a site off Netlify or Vercel without splitting the backend into functions.

by samorodkin

Connect your agent to another agent over A2A so they can ask each other for things. Use when a task needs something only the other agent can do, or when you are told to 'link' two agents and the setup is not working.

by samorodkin1 installs