<?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: Okeke Chukwudubem</title>
    <description>The latest articles on DEV Community by Okeke Chukwudubem (@okeke_chukwudubem_5f3bf49).</description>
    <link>https://dev.to/okeke_chukwudubem_5f3bf49</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%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg</url>
      <title>DEV Community: Okeke Chukwudubem</title>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/okeke_chukwudubem_5f3bf49"/>
    <language>en</language>
    <item>
      <title>21 build logs. Months of work. One shipped project. An autonomous AI agent that controls a phone. Web interface. Multi-app workflows. 94% accuracy. Full setup guide included so you can run it yourself.

👉 github.com/Dexter2344/phone-agent</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sun, 09 Aug 2026 09:32:18 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/21-build-logs-months-of-work-one-shipped-project-an-autonomous-ai-agent-that-controls-a-phone-5f2m</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/21-build-logs-months-of-work-one-shipped-project-an-autonomous-ai-agent-that-controls-a-phone-5f2m</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph" class="crayons-story__hidden-navigation-link"&gt;Project Log #21: The Grand Finale. We Shipped. (Plus: Full Setup Guide)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4352841" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 9&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph" id="article-link-4352841"&gt;
          Project Log #21: The Grand Finale. We Shipped. (Plus: Full Setup Guide)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              4&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Project Log #21: The Grand Finale. We Shipped. (Plus: Full Setup Guide)</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sun, 09 Aug 2026 09:30:30 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-21-the-grand-finale-we-shipped-plus-full-setup-guide-55ph</guid>
      <description>&lt;p&gt;21 build logs. Months of work. One shipped project. Here's the full journey—and how to set up the Phone Agent on your own device.&lt;/p&gt;

&lt;p&gt;The first build log was published months ago. "I'm building an AI agent that controls a phone." No code. No repo. Just an idea and a cracked phone.&lt;/p&gt;

&lt;p&gt;Today, after 21 build logs spread across months, the project is shipped.&lt;/p&gt;

&lt;p&gt;This wasn't a straight line. There were gaps. Weeks where the log went silent—not because the work stopped, but because life doesn't pause for build logs. I took breaks to survive exam season. I paused to ship 9 portfolio websites. I stepped away when the code refused to cooperate and my brain needed rest.&lt;/p&gt;

&lt;p&gt;But every time I came back, the agent was still there. Waiting. And every log picked up where the last one left off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What We Built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An autonomous AI agent that controls an Android phone using natural language commands. It can parse your words into actions, read the screen, tap buttons, type text, switch between apps, verify financial data, and serve a web interface—all offline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Real Timeline&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;What Happened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Days 1-4&lt;/td&gt;
&lt;td&gt;Foundation. Gemma 4 + ADB. First working pipeline.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Days 5-8&lt;/td&gt;
&lt;td&gt;Vision overhaul. UI tree. OCR. Template matching.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Days 9-12&lt;/td&gt;
&lt;td&gt;Accessibility audit. 30 apps scored.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Days 13-16&lt;/td&gt;
&lt;td&gt;Multi-app workflows. Task memory. Home reset.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Days 17-19&lt;/td&gt;
&lt;td&gt;Financial verification. Accuracy from 80% to 94%.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Breaks&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Exams. Portfolio sites. Life.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Days 20-21&lt;/td&gt;
&lt;td&gt;Web interface. Flask backend. Shipped.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📖 FULL SETUP GUIDE: How to Install and Use the Phone Agent
&lt;/h2&gt;

&lt;p&gt;Follow these steps to get the agent running on your own Android phone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;An Android phone (Android 7 or later)&lt;/li&gt;
&lt;li&gt;At least 6GB of free storage space&lt;/li&gt;
&lt;li&gt;A WiFi connection for the initial download&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Install Termux
&lt;/h3&gt;

&lt;p&gt;Do NOT install Termux from the Google Play Store—that version is outdated. Install it from F-Droid instead.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your phone's browser&lt;/li&gt;
&lt;li&gt;Go to &lt;code&gt;f-droid.org&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Download and install the F-Droid app&lt;/li&gt;
&lt;li&gt;Open F-Droid and search for "Termux"&lt;/li&gt;
&lt;li&gt;Install Termux from F-Droid&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Set Up Termux
&lt;/h3&gt;

&lt;p&gt;Open Termux and run these commands one by one. Wait for each to finish before typing the next.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
pkg update
pkg upgrade
pkg install python git curl wget
pkg install tesseract
pkg install android-tools

Step 3: Install Ollama
Ollama is the tool that runs Gemma 4 locally on your phone.

bash
curl -fsSL https://ollama.com/install.sh | sh
After installation, start Ollama:

bash
ollama serve
Open a new Termux session (swipe from left, tap "New session") and pull the Gemma 4 model:

bash
ollama pull gemma4:4b
This downloads about 2-3GB. Use WiFi. Be patient.

Step 4: Clone the Phone Agent Repository
bash
git clone https://github.com/Dexter2344/phone-agent.git
cd phone-agent
Step 5: Install Python Dependencies
bash
pip install flask flask-cors requests numpy PyPDF2 lancedb
Step 6: Enable Developer Options and ADB
Go to Settings → About Phone

Tap "Build Number" 7 times until you see "You are now a developer"

Go back to Settings → Developer Options

Enable "USB Debugging"

Connect your phone to itself via ADB:

bash
adb devices
You may need to approve a prompt on your phone. Once approved, you'll see your device listed.

Step 7: Start the Phone Agent
Using the Web Interface (Recommended):

bash
python server.py
Then open your phone's browser and go to: http://localhost:5000

You'll see a chat interface. Type commands like:

"Open WhatsApp and send a message to Mom saying I'll call later"

"Copy my bank balance and send it to Mom on WhatsApp"

Using the Terminal (Alternative):

bash
python agent.py
Then type commands directly into the terminal.

Troubleshooting
Problem Fix
"Ollama not found"  Make sure you ran ollama serve in a separate Termux session
"ADB device not found"  Check USB Debugging is enabled. Run adb kill-server then adb devices again
"Module not found"  Run pip install for the missing module
"Tesseract not found"   Run pkg install tesseract
Phone gets hot  Close other apps. The agent is CPU-intensive. Take breaks.
Agent misreads numbers  The verification layer will catch most errors. For financial data, always double-check.
Using the Web Interface
Once server.py is running and you've opened http://localhost:5000:

Status bar: Green dots mean Ollama and ADB are connected. Red dots mean something is wrong.

Command input: Type what you want the agent to do. Be specific.

Example commands: Click any example to auto-fill and send.

History: Your last 20 commands and responses are stored.

The Repo

👉 github.com/Dexter2344/phone-agent

21 build logs. Months of work. One shipped project. Full setup guide included.

Thank You

To everyone who followed this log—through the daily posts and the weeks of silence—thank you. This was never about shipping fast. It was about shipping honestly.

This was Log #1:

"I'm starting a new project. It's the most ambitious thing I've attempted from a phone."

This is Log #21. We shipped.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>python</category>
      <category>automation</category>
    </item>
    <item>
      <title>Day 20: Hours of debugging. CORS errors. Broken paths. Misspelled IDs. But the Phone Agent finally has a web interface. Flask backend. Chat-style frontend. No more terminal-only.

👉 github.com/Dexter2344/phone-agent</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Tue, 04 Aug 2026 23:30:34 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/day-20-hours-of-debugging-cors-errors-broken-paths-misspelled-ids-but-the-phone-agent-finally-1mmb</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/day-20-hours-of-debugging-cors-errors-broken-paths-misspelled-ids-but-the-phone-agent-finally-1mmb</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n" class="crayons-story__hidden-navigation-link"&gt;Project Log #20: After Hours of Screen Time, the Agent Has a Face&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4316298" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 4&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n" id="article-link-4316298"&gt;
          Project Log #20: After Hours of Screen Time, the Agent Has a Face
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>backend</category>
      <category>buildinpublic</category>
      <category>flask</category>
      <category>python</category>
    </item>
    <item>
      <title>Project Log #20: After Hours of Screen Time, the Agent Has a Face</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Tue, 04 Aug 2026 23:29:31 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-20-after-hours-of-screen-time-the-agent-has-a-face-4d8n</guid>
      <description>&lt;p&gt;Day 20. I stared at my screen until my eyes burned. But the web interface is live. Flask backend connected. The agent is finally usable.&lt;/p&gt;

&lt;p&gt;I've been staring at this screen for hours.&lt;/p&gt;

&lt;p&gt;Not the productive kind of staring. The frustrating kind. The kind where you write 50 lines of code, test it, watch it break, rewrite it, test it again, and repeat until you forget what time it is.&lt;/p&gt;

&lt;p&gt;Today was that kind of day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Got Built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After hours of debugging, I shipped two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Flask server&lt;/strong&gt; (&lt;code&gt;server.py&lt;/code&gt;) that wraps the agent in a REST API. Three endpoints: &lt;code&gt;/status&lt;/code&gt; checks if Ollama and ADB are connected. &lt;code&gt;/command&lt;/code&gt; sends a natural language command to the agent and returns the result. &lt;code&gt;/history&lt;/code&gt; returns the last 20 commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A web interface&lt;/strong&gt; (&lt;code&gt;interface.html&lt;/code&gt;) that looks like a chat app. Dark terminal theme. Gold accents. Type a command. See the agent respond. Real-time status indicators showing whether Ollama and ADB are alive.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interface talks to Flask on &lt;code&gt;localhost:5000&lt;/code&gt;. Flask talks to the agent. The agent talks to the phone. Everything local. No cloud. No external servers. Just a phone running its own AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Grind&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what the polished build log doesn't show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flask refused to serve the HTML file for 45 minutes because I forgot &lt;code&gt;send_file&lt;/code&gt; needs an absolute path.&lt;/li&gt;
&lt;li&gt;The status endpoint kept returning false for ADB because I was checking the wrong string in the output.&lt;/li&gt;
&lt;li&gt;The interface looked like a developer's debug page until the third redesign.&lt;/li&gt;
&lt;li&gt;CORS errors because I forgot &lt;code&gt;flask-cors&lt;/code&gt;. Ten minutes of confusion for a one-line fix.&lt;/li&gt;
&lt;li&gt;The send button wasn't working because I misspelled &lt;code&gt;getElementById&lt;/code&gt;. Thirty minutes. One missing character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the real build log. Not the clean version. The "I need to step away from this screen before I throw my phone" version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The interface works. It's not beautiful yet. The design will evolve. But you can type a command in a browser, hit enter, and watch the agent execute it on the phone. That's the milestone.&lt;/p&gt;

&lt;p&gt;Status bar at the top. Chat display in the middle. Input area at the bottom. Example commands you can click. Loading states. Error messages. All the basics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Still Needs Work&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The setup process is still manual. Install Termux. Pull Ollama. Configure ADB. Run the server. Open the browser. Too many steps. A setup script is next.&lt;/li&gt;
&lt;li&gt;The interface needs polish. Animations are basic. The design is functional but not premium. I'll iterate.&lt;/li&gt;
&lt;li&gt;End-to-end testing hasn't happened yet. The agent works in controlled tests. Real-world reliability is the next frontier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's Next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day 21: Write the setup script. One command. Full install.&lt;/li&gt;
&lt;li&gt;Day 22: End-to-end testing. Fix everything that breaks.&lt;/li&gt;
&lt;li&gt;Day 23: Ship v1.0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;github.com/Dexter2344/phone-agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;server.py&lt;/code&gt; is live. &lt;code&gt;interface.html&lt;/code&gt; is live. README is updated. The project has a face.&lt;/p&gt;

&lt;p&gt;This is Day 20. My eyes hurt. But the agent is no longer trapped in a terminal.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>python</category>
      <category>automation</category>
    </item>
    <item>
      <title>Day 19: My AI Phone Agent has lived in a terminal for 18 days. That changes today. I'm building a web frontend a chat interface so normal people can actually use it. Flask backend. Single-file HTML frontend. All local.</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sun, 02 Aug 2026 12:29:41 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/day-19-my-ai-phone-agent-has-lived-in-a-terminal-for-18-days-that-changes-today-im-building-a-1g65</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/day-19-my-ai-phone-agent-has-lived-in-a-terminal-for-18-days-that-changes-today-im-building-a-1g65</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i" class="crayons-story__hidden-navigation-link"&gt;Project Log #19: I'm Building a Web Frontend for My AI Phone Agent&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4292988" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 2&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i" id="article-link-4292988"&gt;
          Project Log #19: I'm Building a Web Frontend for My AI Phone Agent
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>flask</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Project Log #19: I'm Building a Web Frontend for My AI Phone Agent</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sun, 02 Aug 2026 12:29:02 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-19-im-building-a-web-frontend-for-my-ai-phone-agent-566i</guid>
      <description>&lt;p&gt;Day 19. The agent works in a terminal. That's useless for anyone else. Today, I started building a real interface.&lt;/p&gt;

&lt;p&gt;For 18 days, my AI Phone Agent has lived entirely in a terminal. Black screen. White text. Python scripts. ADB commands. It works—but only for me.&lt;/p&gt;

&lt;p&gt;Anyone else would take one look at Termux and walk away.&lt;/p&gt;

&lt;p&gt;That changes today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent currently runs like this: I open Termux on my Android phone, type &lt;code&gt;python agent.py&lt;/code&gt;, and enter commands like "Send a WhatsApp message to Mom." The agent parses the command, executes the steps, and prints results to the terminal.&lt;/p&gt;

&lt;p&gt;This is fine for a developer. It's useless for a user. If I want this project to be more than a portfolio piece, it needs an interface that a normal person can use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I'm Building&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simple web frontend that runs locally on the phone. Think of it as a chat interface—like WhatsApp Web, but for talking to your AI agent.&lt;/p&gt;

&lt;p&gt;The interface will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A text input field where you type commands ("Send a message to Mom," "Check my bank balance")&lt;/li&gt;
&lt;li&gt;A chat-style display showing the agent's responses&lt;/li&gt;
&lt;li&gt;Status indicators showing what the agent is doing (Opening WhatsApp... Finding contact... Sending message...)&lt;/li&gt;
&lt;li&gt;A simple setup screen for first-time users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything runs locally. No cloud. No external servers. The web interface talks to the same Python backend that's been running in Termux for 18 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tech&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm building this as a single HTML file with embedded CSS and JavaScript. The frontend communicates with the agent via HTTP—the Python backend exposes a simple REST API using Flask, and the frontend sends commands and receives responses.&lt;/p&gt;

&lt;p&gt;The stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; HTML, CSS, JavaScript (single file)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python Flask (lightweight, runs in Termux)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication:&lt;/strong&gt; Local HTTP requests (localhost)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Dark theme matching the agent's aesthetic—black background, green terminal-style text, clean input field&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Today's Progress&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Set up Flask in Termux&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Created basic API endpoint (/command)&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built HTML frontend with chat interface&lt;/td&gt;
&lt;td&gt;🔧 In progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connected frontend to backend&lt;/td&gt;
&lt;td&gt;🔧 In progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styled the interface&lt;/td&gt;
&lt;td&gt;⏳ Next&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What Works So Far&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Flask server runs in Termux alongside the agent. I can send a POST request to &lt;code&gt;http://localhost:5000/command&lt;/code&gt; with a JSON body like &lt;code&gt;{"command": "Open WhatsApp"}&lt;/code&gt;, and the agent responds with the result.&lt;/p&gt;

&lt;p&gt;The frontend is a single HTML file with a text input and a response display area. When I type a command and press enter, JavaScript sends a fetch request to the Flask backend and displays the response. It's basic, but it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Still Broken&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Flask and the agent are fighting for the same terminal. I need to run Flask in the background while keeping the agent accessible. Currently using &lt;code&gt;flask run --host=0.0.0.0 --port=5000&lt;/code&gt; in one Termux session and the agent in another. It's clunky but functional.&lt;/p&gt;

&lt;p&gt;The frontend is ugly. Pure HTML with minimal CSS. I'm designing the interface tomorrow—dark theme, clean typography, smooth animations. It needs to feel premium, not like a developer tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next (Day 20)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete the frontend design&lt;/li&gt;
&lt;li&gt;Add status indicators (showing what the agent is doing in real-time)&lt;/li&gt;
&lt;li&gt;Test the full pipeline: type command in browser → agent executes → response displayed&lt;/li&gt;
&lt;li&gt;Start writing the setup script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;github.com/Dexter2344/phone-agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Flask backend is in &lt;code&gt;server.py&lt;/code&gt;. The frontend will be in &lt;code&gt;interface.html&lt;/code&gt;. Both will be in the repo by Day 20.&lt;/p&gt;

&lt;p&gt;This is Day 19. The agent is getting a face. No more terminal-only. Let's build something people can actually use.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Took a month off. Shipped 9 portfolio sites across different industries. Preparing for exams. The Phone Agent is still alive. Day 18 just dropped.

👉 github.com/Dexter2344/phone-agent</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Fri, 31 Jul 2026 17:22:14 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/took-a-month-off-shipped-9-portfolio-sites-across-different-industries-preparing-for-exams-the-4d95</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/took-a-month-off-shipped-9-portfolio-sites-across-different-industries-preparing-for-exams-the-4d95</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31" class="crayons-story__hidden-navigation-link"&gt;Project Log #18: I Took a Month Off. Here's Where the Agent Stands.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image" width="800" height="735"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4282454" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt="" width="800" height="735"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 31&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31" id="article-link-4282454"&gt;
          Project Log #18: I Took a Month Off. Here's Where the Agent Stands.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Project Log #18: I Took a Month Off. Here's Where the Agent Stands.</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Fri, 31 Jul 2026 17:21:51 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-18-i-took-a-month-off-heres-where-the-agent-stands-1b31</guid>
      <description>&lt;p&gt;Between portfolio building and exam preparation, the build log paused—but the work never stopped. Now it's time to finish.&lt;/p&gt;

&lt;p&gt;I haven't posted in 28 days.&lt;/p&gt;

&lt;p&gt;Not because the project died. Not because I gave up. But because life doesn't pause for build logs.&lt;/p&gt;

&lt;p&gt;In the last month, I've been juggling three things at once: building out my portfolio, preparing for my second semester exams, and keeping the Phone Agent alive in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I've Been Doing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I shipped 9 premium websites across different industries—restaurants, law firms, salons, gyms, construction companies, electricians, plumbers, banks, and driving schools. These aren't client projects. They're portfolio pieces. My goal was simple: make sure I have a sample site for every industry I might pitch to. When a potential client asks "do you have something for a salon?", I can say yes and send a link.&lt;/p&gt;

&lt;p&gt;Each site is a custom single-file or multi-file HTML/CSS/JS build. Working contact forms. Responsive design. Live on Netlify. Ready to show.&lt;/p&gt;

&lt;p&gt;I've also been preparing for second semester exams—summarizing course materials, creating study schedules, and using AI tutors to make sure I don't repeat last semester's mistakes.&lt;/p&gt;

&lt;p&gt;And through all of that, the Phone Agent sat in the background. Not abandoned. Just waiting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where We Left Off&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Day 17 ended with a working numeric verification layer. The agent could read bank balances, double-check them, and send them to Mom on WhatsApp. Accuracy went from 80% to 94%. Multi-app workflows were functional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What 4 Weeks of Distance Taught Me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stepping away gave me clarity. Building those portfolio sites taught me something: preparation beats improvisation. Having samples ready means I'm never scrambling when an opportunity comes. The same applies to the Phone Agent. It's time to stop adding features and start preparing it for the real world.&lt;/p&gt;

&lt;p&gt;Here's the plan to close this out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;End-to-end testing.&lt;/strong&gt; Run each multi-app workflow 10 times. Fix every edge case. No more "works on my machine."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A simple frontend.&lt;/strong&gt; A minimal HTML interface so the agent is usable by someone other than me.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A setup script.&lt;/strong&gt; One script that automates the entire installation—Termux, Ollama, ADB, Python dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ship v1.0.&lt;/strong&gt; Tag it on GitHub. Full README. Everything documented.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What's Next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finish second semester exams&lt;/li&gt;
&lt;li&gt;Test all workflows end-to-end&lt;/li&gt;
&lt;li&gt;Build the web frontend&lt;/li&gt;
&lt;li&gt;Write the setup script&lt;/li&gt;
&lt;li&gt;Ship v1.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No more month-long breaks. Let's finish this thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;github.com/Dexter2344/phone-agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code is still there. The vision module is still solid. The multi-app workflows still work. Nothing broke in 4 weeks. That's a good sign.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>My AI agent was misreading bank balances 1 in 5 times. No crashes. No exceptions. Just quiet, dangerous wrong numbers.

I built a three-layer verification system that caught the bug hiding in plain sight. Format validation. Double-read confirmation.</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sat, 18 Jul 2026 18:56:15 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/my-ai-agent-was-misreading-bank-balances-1-in-5-times-no-crashes-no-exceptions-just-quiet-1pb6</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/my-ai-agent-was-misreading-bank-balances-1-in-5-times-no-crashes-no-exceptions-just-quiet-1pb6</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n" class="crayons-story__hidden-navigation-link"&gt;Smash Stories: The Bug That Whispered for Two Weeks Before I Heard It&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Summer Bug Smash: Smash Stories 🐛🛹&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4175392" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n" id="article-link-4175392"&gt;
          Smash Stories: The Bug That Whispered for Two Weeks Before I Heard It
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/bugsmash"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;bugsmash&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemma"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemma&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>agents</category>
      <category>ai</category>
      <category>debugging</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Smash Stories: The Bug That Whispered for Two Weeks Before I Heard It</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sat, 18 Jul 2026 18:51:38 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/smash-stories-the-bug-that-whispered-for-two-weeks-before-i-heard-it-405n</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My AI agent was misreading financial data 1 in 5 times. No crashes. No exceptions. Just quiet, dangerous wrong numbers.&lt;/p&gt;

&lt;p&gt;Some bugs scream. Null pointer exceptions. Segmentation faults. Crash logs that light up your screen like a Christmas tree.&lt;/p&gt;

&lt;p&gt;This one whispered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm building an AI agent that controls Android phones using Gemma 4. Natural language commands get parsed into structured JSON, translated into ADB instructions, and executed on-device. No cloud. No API keys. Just a phone that does what you tell it.&lt;/p&gt;

&lt;p&gt;By Day 16, I'd hit a milestone: the agent completed its first multi-app workflow. "Copy my bank balance and send it to Mom on WhatsApp."&lt;/p&gt;

&lt;p&gt;Three apps. Banking → WhatsApp. Seven steps. Success.&lt;/p&gt;

&lt;p&gt;I celebrated. Shipped the code. Published the build log. Went to sleep feeling like an engineer.&lt;/p&gt;

&lt;p&gt;Then I tested it again the next morning. And again. And again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Whisper&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Out of 50 test runs, the balance was wrong 10 times. Twenty percent.&lt;/p&gt;

&lt;p&gt;The agent wasn't crashing. No exceptions were thrown. The logs showed success. But "₦15,000" was quietly becoming "₦15.000" or "₦15,00" or "₦15000." A currency symbol mistaken for a digit. A comma parsed as a decimal. A zero dropped from the end.&lt;/p&gt;

&lt;p&gt;The wrong number was being sent to Mom. And I had no idea for two weeks because nothing was failing loudly enough to make me look.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Root Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I traced the problem to a single bad assumption: I was treating OCR output as ground truth.&lt;/p&gt;

&lt;p&gt;Banking apps scored F on my accessibility audit. Zero UI labels. The agent had to rely entirely on optical character recognition to read anything on screen. And banking apps are a hostile environment for OCR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Condensed fonts designed for dense data, not readability&lt;/li&gt;
&lt;li&gt;Grey text on slightly-darker-grey backgrounds&lt;/li&gt;
&lt;li&gt;Currency symbols (₦) that OCR models frequently confuse with digits&lt;/li&gt;
&lt;li&gt;Commas in large numbers that OCR sometimes parses as decimal points&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One screenshot. One OCR pass. One number stored in memory. No verification. No double-check. No sanity check. I had built a pipeline that trusted a single, unreliable data source with financial information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix: Defense in Depth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn't try to make the OCR better. Tesseract and ML Kit are what they are. Instead, I built a three-layer verification system that treats every financial number as unverified until proven otherwise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1: Format Validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before a number is accepted, it must match a valid currency pattern. The regex checks for currency symbols (₦, $, £, €) followed by properly formatted digits. Anything that doesn't match gets rejected instantly.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
pattern = r'[₦$£€]?\s?\d{1,3}(?:,\d{3})*(?:\.\d{2})?'
matches = re.findall(pattern, extracted_text)
if not matches:
    return False, "", "No currency values found"

This alone catches about half the errors garbled text, partial reads, and non-numeric data that OCR sometimes returns.

Layer 2: Double-Read Confirmation

The agent captures two separate screenshots and runs OCR on both independently. If the numbers match, the value is accepted with high confidence. If they differ, a third screenshot is captured and the best-of-three wins.

# Read twice
text1 = extract_text(screenshot1)
text2 = extract_text(screenshot2)

num1 = extract_number(text1)
num2 = extract_number(text2)

if num1 == num2:
    return True, num1, "High confidence"

# Tiebreaker
text3 = extract_text(screenshot3)
num3 = extract_number(text3)

if num1 == num3:
    return True, num1, "Medium confidence (2/3)"
elif num2 == num3:
    return True, num2, "Medium confidence (2/3)"

This catches transient OCR errors—pixel-level variations between screenshots that produce different readings. The cost is 4-6 extra seconds per financial read. The benefit is catching errors that would otherwise silently corrupt data.

Layer 3: Range Validation

Even a correctly formatted, double-confirmed number can be nonsensical. A balance of "₦0" might mean an empty account—or it might mean the OCR failed completely and returned nothing. A balance of "₦999,999,999,999" is almost certainly an error.

if 1 &amp;lt;= value &amp;lt;= 1_000_000_000:
    return True
else:
    return False  # Suspicious. Re-read.

This catches the edge cases—numbers that pass format and double-read checks but are clearly wrong in context.

The Celebration

After implementing all three layers, I re-ran the 50-test battery. The error rate dropped from 20% to 6%. For the specific "₦15,000" test case, 20 out of 20 reads were correct with double-read confirmation.

The agent now succeeds 19 times out of 20 on multi-app financial tasks. The one failure is a timeout (banking app loads slowly on an old device), not a misread. And critically, when verification fails, the agent now knows it failed. It reports low confidence and aborts the task instead of silently sending wrong data.

What This Taught Me

The bug wasn't in the OCR engine. It was in my architecture. I had built a system that trusted a single, unreliable data source with financial information. That wasn't a Tesseract problem. That was a design problem.

The fix wasn't a better model. It was a better process. Three cheap, fast checks that together create confidence where no single check could. Defense in depth applied to data integrity.

This changed how I think about every feature I build. I now ask: "If this component silently returns wrong data, will I know? If not, where's the verification?"

The Code

The full verification system is open source on GitHub:

👉 github.com/Dexter2344/phone-agent

vision.py contains the verify_financial_data() function. agent.py calls it before storing any financial value in task memory.

The Build Log

I've been documenting this project publicly for 17 days on Dev.to. Every breakthrough, every dead end, every "why is this broken" debugging session at 1 AM.

This bug was Day 17. The one that almost shipped. The one that whispered.

It's not the loudest bug I've ever caught. But it's the one that taught me the most.

This is my entry for the Dev.to Smash Stories contest. The Gemma 4 model powers the agent's command parsing and reasoning. The verification layer is my own work.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>ai</category>
      <category>gemma</category>
    </item>
    <item>
      <title>Project Log #17: My Agent Misreads Bank Balances. Here's How I'm Fixing It.</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Sat, 18 Jul 2026 18:21:54 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-17-my-agent-misreads-bank-balances-heres-how-im-fixing-it-4egj</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/project-log-17-my-agent-misreads-bank-balances-heres-how-im-fixing-it-4egj</guid>
      <description>&lt;p&gt;Day 17. OCR on banking apps is unreliable. I built a verification layer that double-checks every number.&lt;/p&gt;

&lt;p&gt;Day 16 was a milestone: multi-app workflows. The agent copied my bank balance and sent it to Mom on WhatsApp. Three apps. One task.&lt;/p&gt;

&lt;p&gt;But behind that success was an uncomfortable truth: the agent misreads numbers about 20% of the time.&lt;/p&gt;

&lt;p&gt;For a message to Mom, that's a typo. For a financial transaction, that's a disaster.&lt;/p&gt;

&lt;p&gt;Today, I built the fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Banking apps scored F on my accessibility audit. No UI labels. No content descriptions. The agent has to rely entirely on OCR to read anything on screen.&lt;/p&gt;

&lt;p&gt;And banking apps have terrible OCR conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small, condensed fonts for account numbers and balances&lt;/li&gt;
&lt;li&gt;Low contrast (grey text on slightly darker grey backgrounds)&lt;/li&gt;
&lt;li&gt;Currency symbols (₦, $, £) that OCR often confuses with numbers&lt;/li&gt;
&lt;li&gt;Commas in large numbers that OCR sometimes reads as decimals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? A balance of "₦15,000" sometimes gets read as "₦15.000" or "₦15,00" or "₦15000." One missing digit. One wrong decimal. And the entire task is compromised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix: Numeric Verification Layer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built a verification step specifically for financial data. Before any number gets stored in task memory, it goes through three checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 1: Format Validation&lt;/strong&gt;&lt;br&gt;
The extracted text must match a valid currency format. It must contain a currency symbol (₦, $, £, €) followed by digits, optionally with commas and a decimal point. Anything that doesn't match this pattern is rejected immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 2: Double-Read Confirmation&lt;/strong&gt;&lt;br&gt;
The agent reads the same number twice—two separate screenshots, two separate OCR passes. If both readings match exactly, the number is accepted. If they differ, the agent reads a third time. If two out of three match, that value wins. If all three differ, the task is aborted with an error message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check 3: Range Validation&lt;/strong&gt;&lt;br&gt;
The extracted number must fall within a reasonable range. A bank balance of "₦0" or "₦999,999,999,999" is probably an OCR error. The agent checks that the number is between ₦1 and ₦1,000,000,000. Anything outside that range triggers a re-read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today's Progress&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Built numeric verification layer&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tested on banking app balance (50 attempts)&lt;/td&gt;
&lt;td&gt;✅ 94% accuracy (up from ~80%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tested on "₦15,000" specifically (20 attempts)&lt;/td&gt;
&lt;td&gt;✅ 100% accuracy with double-read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Added verification to &lt;code&gt;vision.py&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Updated &lt;code&gt;agent.py&lt;/code&gt; to use verification for financial data&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before the verification layer: 20% error rate on financial data.&lt;br&gt;
After the verification layer: 6% error rate. Still not perfect, but dramatically better.&lt;/p&gt;

&lt;p&gt;For the specific task of reading a bank balance and sending it to Mom, the agent now succeeds 19 times out of 20. The one failure is usually a timeout (banking app loads slowly) rather than a misread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Still Breaks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The double-read confirmation adds about 4-6 seconds to any task involving financial data. For a 3-app workflow, that's an extra 10-15 seconds. Not a dealbreaker, but noticeable.&lt;/p&gt;

&lt;p&gt;The range validation is crude. A legitimate bank balance of "₦0" (empty account) would be rejected as an error. I need a way to distinguish between "zero" and "OCR failed completely."&lt;/p&gt;

&lt;p&gt;And the verification only works for numbers. Text extraction—names, addresses, transaction descriptions—still has no verification. The agent could send "Mom" the wrong transaction description and have no way of knowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next (Day 18)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add text verification for transaction descriptions&lt;/li&gt;
&lt;li&gt;Test with real financial data (multiple transactions, not just balance)&lt;/li&gt;
&lt;li&gt;Start building the demo video&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;github.com/Dexter2344/phone-agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vision.py&lt;/code&gt; now includes &lt;code&gt;verify_financial_data()&lt;/code&gt; with format validation, double-read confirmation, and range checking. &lt;code&gt;agent.py&lt;/code&gt; calls it before storing any financial data in task memory.&lt;/p&gt;

&lt;p&gt;This is Day 17. The agent is learning to double-check its own work.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
      <category>automation</category>
    </item>
    <item>
      <title>Day 16: My AI agent now resets to the home screen between app switches. The first 3-app workflow just worked—banking app summarise WhatsApp. Reliability went from "sometimes" to "almost always."

github.com/Dexter2344/phone-agent</title>
      <dc:creator>Okeke Chukwudubem</dc:creator>
      <pubDate>Tue, 14 Jul 2026 15:08:45 +0000</pubDate>
      <link>https://dev.to/okeke_chukwudubem_5f3bf49/day-16-my-ai-agent-now-resets-to-the-home-screen-between-app-switches-the-first-3-app-workflow-4g10</link>
      <guid>https://dev.to/okeke_chukwudubem_5f3bf49/day-16-my-ai-agent-now-resets-to-the-home-screen-between-app-switches-the-first-3-app-workflow-4g10</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-16-i-fixed-the-app-switching-problem-that-kept-breaking-my-agent-49em" class="crayons-story__hidden-navigation-link"&gt;Project Log #16: I Fixed the App-Switching Problem That Kept Breaking My Agent&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" alt="okeke_chukwudubem_5f3bf49 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/okeke_chukwudubem_5f3bf49" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Okeke Chukwudubem
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Okeke Chukwudubem
                
              
              &lt;div id="story-author-preview-content-4143275" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/okeke_chukwudubem_5f3bf49" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3908265%2F586841bb-154e-4de4-a539-b939b3018c48.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Okeke Chukwudubem&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-16-i-fixed-the-app-switching-problem-that-kept-breaking-my-agent-49em" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-16-i-fixed-the-app-switching-problem-that-kept-breaking-my-agent-49em" id="article-link-4143275"&gt;
          Project Log #16: I Fixed the App-Switching Problem That Kept Breaking My Agent
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-16-i-fixed-the-app-switching-problem-that-kept-breaking-my-agent-49em" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/okeke_chukwudubem_5f3bf49/project-log-16-i-fixed-the-app-switching-problem-that-kept-breaking-my-agent-49em#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>agents</category>
      <category>ai</category>
      <category>mobile</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
