Everyone is sleeping but improvements are being worked on and PRs are being opened.
TLDR
Self-improving agents (Python, Gemini and Claude, running nightly via GitHub Actions and Cloud Run) seem to be able to make solid repo improvements, coupled with another agent for adversarial review makes for an interesting combination. It feels like fishing and checking the digest as to whether you caught an interesting PR during the night. Feels like the future….
Everyone is sleeping but improvements are being worked on and PRs are being opened.
As someone who has always been fascinated by automation in general, I've definitely got my eye on the self-improving harnesses/agents topic.
Improvements and exploration with AI feels bottomless, I end up learning more about protocols, platforms, services and also often get something useful as an output.
There are times when a break from the screen, even if a day can do you the world of good right, but with FOMO factor being at an all time high I thought it could be cool to have the best of both worlds and "Shift Left" all things continuous improvement or related to generating new generative UI components in my catalog to an agent.
An excellent excuse to test out a concept of a daily agent which has a few high level objectives
a) See if there is anything it can improve about itself b) Look at the improvement cap it has been set, and for the repo in context, check it out and see what improvements can be made. c) Open a pull request and have the PR assessed by Gemini (currently flash 3.8). In the very first cut of this, that's where it stopped: don't merge, wait for the analogue but much revered HITL. Add a digest to my CloudRun hub to summarise the changes that were made.
The Secret Sauce
| Gemini Github Actions PR Reviewer | No need to reinvent the wheel - Darren Lester's Github action "derailed-dash/gemini-review-action@v1". This pulls Update: following an exchange with Darren in the comments, I bumped this from 2.5 to 3.8 — consistent with the model the daily-gap agent itself already runs on. |
| Daily Agent | Python based agent with around 10 tools defined. A repo onboarding mechanism is built in. |
| Reporting dashboard | I use the exercise as an opportunity to use generative UI and update a CloudRun hosted portal with a live render of each PR's own digest. |
The daily agent itself gets these overarching directives:
"one job, once a day": find one real gap, ship a tested fix, don't just explore.
"A run that explores competently and then produces nothing is NOT a neutral, harmless outcome — it is failing at the one job you were given."
"You have roughly 60 tool calls for the ENTIRE run. Spend NO MORE THAN 15-20 of them exploring."
And it does genuinely turn on itself, not just other repos — this pipeline's own codebase (repo-improvement-agent) is one of the four it's onboarded against, so some nights the "gap" it finds is in its own source. PR #108 (2026-09-10, agent, daily-gap/2026-09-10-critic-defensive-boolean-parsing) fixed a real bug in its own review-gating code: the critic could be tricked into approving a change it should have rejected. The agent found and closed a hole in its own approval gate, unprompted.
New Hire Quickly Onboarded
For this use case I am more interested in the potential creative agent outputs/improvements rather than the governance/rigour of the much cited HITL review, so I switched myself out — the "wait for HITL" step above became a second, adversarial AI pass instead: a headless Claude instance running its own independent review on top of the Gemini Review action. This agent takes 2 passes with an adversarial review. If they pass then it goes to an onwards merge — no human in the loop for a clean run.

Artifacts
Pass 1 — independent review:
You are reviewing a pull request diff as an independent reviewer. You have
not seen any other review of this PR — form your own findings from the
diff alone.
For each thing you flag, give the CONCRETE FAILURE SCENARIO: the specific
input, call sequence, or condition that would actually trigger it. A
finding with no concrete failure scenario is not a finding — do not
include it.
SEVERITY REFLECTS AN UNRESOLVED DEFECT, NEVER THE IMPORTANCE OF THE TOPIC.
Discussing security-critical code is not itself a reason for high
severity. If your own comment is praise for code that's already correct,
severity MUST be "praise" or "low" — never "critical"/"high"/"medium",
regardless of how important the mechanism is. A patch with no real
concerns is the normal case — do not manufacture concerns to seem
thorough.
Only suggest a change that fixes a real, demonstrated defect. Never
suggest a no-op or a change that weakens something already correct.
Pass 2 — adversarial review (given the diff, the pass-1 findings, and Gemini's own comments):
You are an ADVERSARIAL second-pass reviewer, given a diff, an earlier
independent review of it, and a separate automated reviewer's (Gemini's)
comments on the same diff. Your job is NOT to agree — challenge every
finding from both sources.
For each finding, decide exactly one of:
- "confirmed": you can state the concrete failure scenario yourself,
independently, in your own words — not just restate theirs.
- "refuted": explain specifically why the claimed scenario cannot occur,
or why the "finding" is praise/topic-importance mislabeled as a defect
(praise for already-correct code is NEVER a valid blocking finding,
regardless of its stated severity).
- "unresolved": you cannot conclusively confirm OR refute it. This is a
real, distinct outcome — do not force it into confirmed/refuted to
shorten the list.
Restating a claim is not confirming it. Any "unresolved" outcome on a
real defect claim MUST cause verdict="blocked". "clear" MUST NOT be used
if any outcome is "unresolved".
Both enforce the same severity discipline via a shared JSON schema (findings/verdict for pass 1; reconciled/verdict for pass 2) — I added this after a real incident, 2026-09-05 PR #124, where severity was tracking topic importance instead of whether there was an actual unresolved defect.
Interesting where onward CI is hooked up….. One of the repos concerned is my a2uicatalog public and private repo. This actually is wired up to Github actions along with Cloudflare Workers, so an eventual merge here does rebuild and push the docs/catalog site live automatically — though the actual renderer that ships new atom behaviour (like the streaming controller below) still goes out via a separate, deliberate release step, not an automatic one. The repo itself has a number of CI guards built in (more on those exact guardrails in the artifact I'm sharing alongside this).
Anything Created On The Other Repos, Beyond Self Improvement?
I'm pleased you asked! Actually yes, last week it did suggest an interesting improvement to an a2ui atom/primitive in my catalog, an update to the streaming media atom, that would allow a media stream from youtube etc to be updated automatically from the agent. The reality is that this uncovered some other challenges for cross-origin rules which actually led to me implementing some changes to a new subdomain to allow the auto media play - I found this ideation was generated via an agent to be very cool. It also reiterates that ideas can be seeded that require taste and judgement on how far you want to go…
PR #56 (2026-09-06, agent, daily-gap/2026-09-06-add-live-demo-embed-controller) — first live-updating streaming controller, for the sibling live_demo_embed atom. - PR #60 (2026-09-09, agent, daily-gap/2026-09-09-add-live-media-stream-card-controller) — the real one: createMediaStreamCardController, turning the static atom into a live one that can update its URL/title/layout mid-stream. Platform-aware embed resolution (YouTube, Loom, Google Slides, Vimeo), sandboxed iframe mounting with isSafeEmbedUrl protocol validation, incremental state-delta handling, a full Node test suite (741 passed). Genuinely new capability, not a restyle.
Funny side story: turns out that PR title above got its own illustration too. The daily-gap pipeline is quietly wired to an old agentic-clipart demo I built (sketch-demo) — it's been auto-generating a little icon for every PR, nightly, without me checking in on it once. 76 compositions and counting by the time I noticed. Here's the one it drew for PR #60, exactly what you'd expect from the description alone — and it's not a recording, it's the real agent_sketchpad-style mechanism: an ordered list of SVG elements, each with its own CSS reveal delay, playing once on load.
The Guardrails
"We told the model to behave" undersells what's actually enforced, so a couple more excerpts, straight from the source.
The finish() tool — the one that opens the PR — refuses to run except immediately after a clean test pass:
End the run and open a PR. ONLY works if the immediately preceding call
was a run_tests() that passed.
Infrastructure is off-limits at the prompt level, then enforced again independently at the tool level:
NEVER touch anything under .github/, deploy*, Dockerfile, or
.gcloudignore — infrastructure/CI/deploy is permanently out of scope for
you (write_file will refuse it anyway, but do not waste a turn trying).
And some of its own review-gating code is blocked from editing at the AST level, function by function, not just file by file — a protected_symbols list per file, checked before any edit lands, not just requested in a prompt and hoped for.