Agent Skills · Field Manual · No. 3 Try it Install GitHub

A wall of text. Filter what matters.

The minimum you need to see,
collected at the end of the message.

An agent writes long because meaning takes a map of words to carry, and that part is not yours to fix. What the wall cannot do is keep its parts apart: the one sentence that matters, the map that got there, and the things that need you all arrive in the same voice. So the asks get collected at the end.

Plate IThe instrument

Find the four asks in here.

One message, as it arrives. Four things in it need an answer from you, and all four sit mid-paragraph, in the same voice as everything around them. Press the button to see them marked, and the section the skill adds at the bottom of every reply.

the reply · 321 words need you · 4 you have to read · 321 words
assistant

The export endpoint is wired to the queue now and the happy path passes locally. A few things worth knowing about how it ended up.

Batching turned out to be the interesting part. R2 accepts a multipart upload of any size, but the worker's memory ceiling rules out holding a full month of rows before a flush, so I settled on chunks of five thousand rows. That keeps peak memory near 40 MB on the largest tenant in the seed data, with headroom for the wide columns. The retry budget I had to guess at: three attempts on a two-second backoff, copied from the ingest path — which is idempotent, and this one is not yet.

There is a schema wrinkle. export_job.tenant_id is plain text rather than a foreign key, which I read as deliberate given the sharding plan, so I left it alone and added an index instead. The migration is generated and applied nowhere. Checkpointing writes a row per chunk so a resumed job picks up at the last committed offset, which also gives us a cheap progress read for the dashboard later.

On naming: I kept exportJob in the service layer and export_job in SQL, matching what the ingest module already does, so the mapping stays boring. The queue consumer is its own module rather than a branch inside the existing one, because the two share nothing but the R2 client.

Tests cover the chunker and the checkpoint resume. The end-to-end test is skipped, since it needs a real R2 binding — worth deciding whether CI runs it at all, at about ninety seconds and real storage per run. The unit tests run in the workers pool and take four seconds.

Before this goes to staging I need to know whether the nightly cron still points at the old bucket. If it does, applying the migration starts writing into a live path. Everything else is ready to go behind that.

The block did not shorten the reply. Everything above it is still there, because that is how the answer got written and no instruction reliably stops it. What changed is that acting on the reply no longer needs a full read of it.


Plate IIWhy it happens

The wall is not the mistake.

01 · The map is the work “a few things worth knowing”

Meaning takes a map of words to carry, and the reasoning, the alternatives and the caveats are what make an answer worth trusting rather than merely confident. Cut them and you get a confident sentence with no way to check it.

02 · Everything shares one stream “I had to guess at the retry budget”

The ask lands where the reasoning reached it: mid-paragraph, in the same voice as the map around it, pointing at something four messages back. Nothing marks it as the part addressed to a person.

03 · So it goes unanswered asked again, three turns later

You hunt for it, or you miss it — and when the agent asks a fourth time, the question no longer makes sense on its own, because it needed the paragraph it came out of.

So this filters rather than shortens. One section at the end holds everything that needs a person — a blocker, a decision, an assumption, a risk, a question — and reading the wall above it becomes optional.


Plate IIIThe test

Does a person have to see it?

That is the whole filter, and it is not the same question as how important a sentence sounds. Run it over the reply from Plate I and four lines pass. Everything else in there is worth having and needs nothing from you.

passes The nightly cron may still point at the old bucket, and staging waits on it.
passes Three retry attempts, copied from a path that is idempotent when this one is not.
passes The end-to-end test is skipped, and running it in CI costs ninety seconds.
passes tenant_id was left as plain text on an assumption about sharding.
no Peak memory sits near 40 MB on the largest tenant in the seed data.
no The queue consumer is its own module, since it shares only the R2 client.
no Checkpoints write a row per chunk, so a resumed job picks up where it stopped.

Plate IVWhat makes it work

Two rules, and one of them carries it.

Every item stands on its own.

This is the load-bearing one. An item that points at the paragraph above is answerable only by somebody who just read the wall — the reader you were sparing. Name the thing, then ask.

✕the second option above
✓the retry budget on the export queue: 3 attempts, or 1

Nothing. is a real answer.

An empty section says so out loud. That is what makes a quiet turn readable at a glance instead of ambiguous — the difference between nothing needed and nobody looked.

✕(section omitted)
✓## NEEDS YOUR ATTENTION
Nothing.

This is a filter, not a budget. A reply that shortens itself into ambiguity has traded one cost for a worse one.

Try it

Try it for a session, or keep it.

The whole skill is a block of text. One command turns it on where you are standing, and another writes it into AGENTS.md so every session starts with it.

Read the last section first for a week. If the answers stop needing a full read to act on, keep it.

  1. 1

    Fetch the skills

    npx skills@latest add franciscohermida/skills

    Asks which skills you want and which agents to put them on. Claude Code, Codex, Cursor. Add -g for every project on the machine.

  2. 2

    Turn it on for the session you are in

    /attention

    Replies end with the section from that turn on. Nothing is written anywhere, so it costs one word to try and ends when the session does.

  3. 3

    Or keep it, in the project you want it in

    /setup-attention

    Writes one block into AGENTS.md. That is the entire footprint, and every reply after it ends with what needs your attention.