<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Victor Perdiz Sanz</title>
    <description>The latest articles on DEV Community by Victor Perdiz Sanz (@feelsgo).</description>
    <link>https://dev.to/feelsgo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4102320%2F9f70a891-a9e0-448c-b8df-4abab829b551.png</url>
      <title>DEV Community: Victor Perdiz Sanz</title>
      <link>https://dev.to/feelsgo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/feelsgo"/>
    <language>en</language>
    <item>
      <title>AupaZu — An Agent That Drafts Grant Applications, and Refuses to Submit Them published</title>
      <dc:creator>Victor Perdiz Sanz</dc:creator>
      <pubDate>Mon, 31 Aug 2026 07:47:38 +0000</pubDate>
      <link>https://dev.to/feelsgo/aupazu-an-agent-that-drafts-grant-applications-and-refuses-to-submit-them-published-25j5</link>
      <guid>https://dev.to/feelsgo/aupazu-an-agent-that-drafts-grant-applications-and-refuses-to-submit-them-published-25j5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxm55zlcdiwtkf536qwk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxm55zlcdiwtkf536qwk.jpg" alt=" " width="800" height="447"&gt;&lt;/a&gt;The problem&lt;br&gt;
Small retailers miss public money. Not because the grants don't exist — the Basque Country, where my pilot city Vitoria-Gasteiz sits, publishes them regularly — but because the eligibility rules live in dense PDFs, the deadlines are short, and a two-person bakery has no grants department. The application itself is the final friction point: forms that demand exact epigraph codes, investment categories and municipal details that the owner half-knows.&lt;/p&gt;

&lt;p&gt;I wanted to build an agent that does the heavy lifting — watching, matching, asking, drafting — while being honest about the one thing it must never do: hit "submit" on someone's behalf.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9szdt5jskdgjv2flme0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9szdt5jskdgjv2flme0.jpg" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
What the agent does&lt;br&gt;
AupaZu is an event-driven pipeline with a human gate at the end:&lt;/p&gt;

&lt;p&gt;A Cloud Scheduler job (HTTP + OIDC) wakes the system every morning.&lt;br&gt;
New grant calls are detected and normalized into a typed graph.&lt;br&gt;
A matcher scores each call against each merchant's profile.&lt;br&gt;
If a fact is missing — say, the investment amount — a Gap Analyst agent asks exactly one question over WhatsApp, in plain language.&lt;br&gt;
The merchant's reply updates the profile; the eligibility explanation is regenerated, and every claim carries a citation ID pointing to the official source.&lt;br&gt;
A Draft Builder produces a versioned draft. Confirmed facts only. Anything missing appears as a [PENDING: field] marker — never an invented value.&lt;/p&gt;

&lt;p&gt;End to end, the full cycle takes about 85 seconds. You can watch a real run here:&lt;/p&gt;

&lt;p&gt;🎥 Demo video (3 min)&lt;br&gt;
How it's built&lt;br&gt;
Google ADK orchestrates six small agents (Orchestrator, Curator, Matcher, Synthesizer, Gap Analyst, Draft Builder).&lt;br&gt;
Gemini 3.7 Flash on Vertex AI does the reasoning; the runtime runs on two Cloud Run services — a private brain and a public webhook that Meta can reach.&lt;br&gt;
Pub/Sub carries domain events (grant.detected, message.received, match.ready, merchant.profile.updated…), each with an event_id for idempotency and a correlation_id that survives the whole journey — visible in Pub/Sub, in Cloud Run logs, and in the case file itself.&lt;br&gt;
Supabase/PostgreSQL is the system of record, with migrations versioned in the repo.&lt;br&gt;
Secret Manager holds every credential; the runtime service account is least-privilege.&lt;br&gt;
Governance is the feature&lt;br&gt;
The most important line of the product is printed on every draft: "DRAFT — AupaZu does not submit the application; human review is mandatory." There is deliberately no submit tool, no endpoint, no button.&lt;/p&gt;

&lt;p&gt;That principle shows up in smaller decisions too. The system of record never stores a phone number — only a reference token. Every demo merchant is a fictitious persona flagged is_demo: true inside the database itself. And the repo keeps a written list of everything still imperfect: nine known debts, from missing dead-letter queues to IAM scope. What is written down is never a surprise.&lt;br&gt;
The freeze as evidence&lt;br&gt;
Before the final end-to-end run, I defined the acceptance criterion in the spec: two consecutive full runs under five minutes, no manual retries, with console evidence. The first attempt took ten minutes — a cold pull subscription — so a warm-up run became part of the drill. Then: 1 min 25.6 s, and 1 min 16.8 s, back to back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdp5ha1p84zts3c9oru2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdp5ha1p84zts3c9oru2.jpg" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
The freeze also caught two real bugs the test suite had missed: a database CHECK constraint that rejected the canonical event name merchant.profile.updated, and a webhook validator that returned 403 to legitimately signed Meta callbacks. Both were fixed with migrations, re-verified, and documented with their commit hashes. The freeze wasn't a phase of fear — it was a phase of evidence.&lt;br&gt;
What I learned&lt;br&gt;
Observability designed for operations turned out to be the best demo material: one correlation ID, filterable logs, saved queries.&lt;br&gt;
A written debt list builds more trust with reviewers than a polished claim of completeness.&lt;br&gt;
Next time, specs live in the repo from day one — retrofitting governance works, but costs double.&lt;/p&gt;

&lt;p&gt;That is how I believe agents should be built: drafts that are automatic, decisions that stay human, and receipts for everything.&lt;br&gt;
Links&lt;br&gt;
🎥 Demo video &lt;a href="https://youtu.be/2iESHE0NlbA" rel="noopener noreferrer"&gt;https://youtu.be/2iESHE0NlbA&lt;/a&gt; &lt;br&gt;
🏆 All Things Agentic Hackathon,&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>gemini</category>
      <category>vertexai</category>
      <category>allthingsagentichackathon</category>
    </item>
  </channel>
</rss>
