DEV Community

Shir Meir Lador for Google AI

Posted on Originally published at Medium

Build a Long-Running Agent in the Cloud for $5.70/Month

How do you run an autonomous AI agent in the cloud 24/7 for just $5.70 a month?

I recently wanted to build a background worker with persistent disk storage and an instant web dashboard, but I didn't want the headache of managing a virtual machine or paying a massive monthly bill.

If you are building long-running agents, you know this exact cloud hosting dilemma:

  1. Standard serverless (like Cloud Run services or Lambda): When traffic stops, the container scales to zero — instantly killing your background loops and wiping your agent's active memory (RAM). On the flip side, a sudden traffic spike spins up multiple containers that can overwrite each other's state files and corrupt your data. (Note: Save state using JSON or Markdown files. Avoid SQLite, as Cloud Run volume mounts)
  2. A regular virtual machine (like EC2 or Compute Engine): Keeps your agent running 24/7, but a standard 1-vCPU machine typically costs $15 to $25 a month even when idle. Even if you use a heavily-throttled fractional VM for $7/month, you are still stuck with the full infrastructure management overhead.

Last year, I built a multi-agent Trend Spotter with ADK. It worked well, but I wanted to make it fully autonomous: a continuous, long-running agent that scans and summarizes tech feeds in the background without manual triggers or high hosting costs.

Google Cloud's new Cloud Run instances primitive solves this exact problem. It gives you a single, always-on container that runs 24/7, costs $5.70 a month on a shared CPU, provides a free HTTPS endpoint, and lets you mount cloud storage like a normal local disk.

Here is how to build and deploy a production long-running agent with this setup (you can follow along with the complete source code in the repo.

What are we building?

I want to stay up to date with what is happening in AI and agent engineering. But instead of manually opening 20 browser tabs across different websites every morning, I wanted to build my own long-running agent that updates me on recent news anytime I want.

Personal tech briefing agent UI

Personal tech briefing agent UI

 
Here is what the agent does:

  • Runs continuously as a background daemon: Wakes up automatically every 30 minutes to collect fresh news. Note that Cloud Run instances restart automatically up to every 7 days, so your agent just needs to gracefully resume its schedule when restarted.
  • Scans Hacker News and other curated AI and agent engineering sources.
  • Accepts real-time alerts & mobile shares: Includes an inbound webhook (POST /api/webhook) so you can push breaking tweets, iOS Share Sheet links, or GitHub releases straight into the agent for instant summarization.
  • Filters the noise: Strips out paywalls, ads, and low-substance articles.
  • Summarizes with Gemini 2.5 Flash: We use Gemini 2.5 Flash to keep costs low. You can swap in the newer Gemini 3.5 or 3.6 Flash models if you need advanced reasoning, but note that their input tokens cost 5x as much compared to 2.5 Flash ($1.50 vs $0.30 per 1M tokens). For simple daily summarization, 2.5 Flash (or the equally cheap Gemini 3.5 Flash-Lite) is fast, highly capable, and keeps the monthly API bill to just a few cents.
  • Saves data safely: Stores the daily markdown briefing and seen URLs directly in a mounted cloud storage folder (/data).
  • Serves a clean web dashboard: Gives an instant web page to read your briefing or trigger a fresh run whenever you want.

How the system works

The whole application runs inside one Cloud Run instance:

Tech briefing agent architechture

Tech briefing agent architechture

 

What else can you build with a long-running agent?

A tech briefing agent is just one example. Because Cloud Run instances give you an always-on background worker, a free web endpoint, and safe local disk storage, you can use this exact same pattern for many developer workflows:

  1. Persistent Slack, Discord, or Telegram Bot: A bot that maintains long-lived connections to chat gateways, answers developer questions, and syncs unresolved issues to your backlog.
  2. Security & Vulnerability Watchdog: An agent that runs on an internal timer to monitor dependencies and CVE security feeds, caching vulnerability signatures on local disk.
  3. DevOps Incident Triage Co-Pilot: An agent that receives incoming webhook alerts from monitoring tools, runs background log queries without timing out, and renders an instant root-cause dashboard.
  4. Pull-Based Queue Worker: An agent that continuously pulls complex tasks from Pub/Sub, Kafka, or RabbitMQ, performs multi-step LLM reasoning, and writes results to storage.
  5. Nightly CI/CD & Flaky Test Fixer: A background daemon that runs overnight test suites, analyzes test logs to spot flaky tests, and opens pull requests with automated fixes.

Why Cloud Run instances are great for agents

Standard serverless platforms are designed for quick web requests. They wait for a user to click a button, run for one second, and shut down.

Long-running background agents have different needs:

Comparison — Standard Serverless / Regular VMs / Cloud Run Instances

Comparison — Standard Serverless / Regular VMs / Cloud Run Instances

 

With an instance, you get the simplicity of serverless with the stability of a VM. Because your instance is always hot with a public HTTPS endpoint, it easily handles three trigger styles in one container:

  1. Periodic Background Polling: Runs autonomously on an internal asyncio schedule without needing external cron services.
  2. Instant Web Dashboard: Zero cold starts when you open the reading dashboard.
  3. Real-Time Push Webhooks: An inbound POST /api/webhook route that lets you push breaking tweets, iOS share sheet links, or GitHub release alerts straight into the agent for immediate summarization.

When NOT to use this

Cloud Run instances are great for single-worker background agents. You should pick a different tool if you need:

  • Massive parallel batch jobs: If you need to process 10,000 documents at once across 100 parallel workers, use Cloud Run Jobs or GKE. An instance is a single worker.
  • High-traffic, bursty web APIs: If your website gets sudden spikes of millions of requests, use standard Cloud Run services so your app can automatically autoscale to hundreds of containers and scale down to zero when traffic stops.
  • Heavy local GPU model hosting: If you want to host an open 70B model directly inside your container on a dedicated H100 GPU, use GKE or Compute Engine. Cloud Run instances are built for CPU applications that connect to hosted models like Gemini.

Alternative architecture: Decoupled Job + Service

Instead of a single instance, you could build an event-driven system: a Cloud Scheduler triggers a Cloud Run Job for polling, while a scale-to-zero Cloud Run Service hosts the dashboard and listens for webhooks.

While this decoupled approach drops compute costs to virtually $0.00 in the free tier, you lose single-container simplicity. You are forced to manage multiple cloud services and message queues (to prevent concurrent webhooks from corrupting your state), while accepting cold starts on your web dashboard.

Compare instances with Decoupled Job + Service for this task

Compare instances with Decoupled Job + Service for this task

 

Deploy your long-running agent in 6 simple steps

You can deploy this setup to Google Cloud in about five minutes.

1. Turn on the cloud services

export PROJECT_ID="your-project-id"
export REGION="us-west1"
export BUCKET_NAME="${PROJECT_ID}-agent-data"
export REPO_NAME="agent-repo"
gcloud config set project $PROJECT_ID
gcloud services enable run.googleapis.com storage.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com secretmanager.googleapis.com
Enter fullscreen mode Exit fullscreen mode

Note: Cloud Run instances are not available in every region. Please pick a supported region near you from the Cloud Run instances locations page.

2. Create a storage bucket for your data

gcloud storage buckets create gs://$BUCKET_NAME \
  --location=$REGION \
  --uniform-bucket-level-access
Enter fullscreen mode Exit fullscreen mode

3. Build your container

gcloud artifacts repositories create $REPO_NAME \
  --repository-format=docker \
  --location=$REGION
gcloud builds submit \
  --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/tech-briefing-agent:latest .
Enter fullscreen mode Exit fullscreen mode

4. Create a service account

gcloud iam service-accounts create briefing-agent-sa \
  --display-name="Briefing Agent SA"
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \
  --member="serviceAccount:briefing-agent-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/storage.objectUser"
Enter fullscreen mode Exit fullscreen mode

5. Store your API key securely

Never pass API keys in plain text. Store your Gemini API key in Google Cloud Secret Manager and grant your service account permission to read it:

echo -n "YOUR_GEMINI_API_KEY" | gcloud secrets create gemini-api-key \
  --data-file=- \
  --replication-policy="automatic"
gcloud secrets add-iam-policy-binding gemini-api-key \
  --member="serviceAccount:briefing-agent-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"
Enter fullscreen mode Exit fullscreen mode

6. Launch the instance

gcloud beta run instances create tech-briefing-agent \
  --image=${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/tech-briefing-agent:latest \
  --region=$REGION \
  --port=8080 \
  --cpu=1 \
  --memory=1Gi \
  --public \
  --service-account=briefing-agent-sa@${PROJECT_ID}.iam.gserviceaccount.com \
  --add-volume mount-path=/data,type=cloud-storage,mount-options="uid=1000;gid=1000;file-mode=0700;dir-mode=0700",bucket=$BUCKET_NAME \
  --set-secrets "GEMINI_API_KEY=gemini-api-key:latest" \
  --set-env-vars "DATA_DIR=/data,POLL_INTERVAL_MINUTES=30"
Enter fullscreen mode Exit fullscreen mode

We set --cpu=1 and --memory=1Gi to keep the cost at $5.70. If you omit these, it defaults to 2 CPUs and 2 GiB (~$11.40/month, see pricing table). To improve load times, you can increase the CPU and memory.

[!TIP] Adjust uid=1000;gid=1000 in the mount-options flag to match the specific non-root user ID defined in your Dockerfile, if different.

When this command finishes, Cloud Run gives you a live HTTPS web address. Open it in your browser to see your briefing dashboard.

What does this cost in real life?

Here is the real monthly bill for running this 24/7:

Monthly cost breakdown

Monthly cost breakdown

 

For less than the price of two cups of coffee, you have a private agent running day and night.

Learn more about Cloud Run instances

Want to dive deeper into Cloud Run Instances? Check out these official Google Cloud resources:

What is coming next?

Now that the hosting problem is solved, how do you make the agent smart and resilient? How do you stop it from summarizing noise when it hits a paywall, or build self-correcting reflection loops?

Join us in the next part where we will dive into graph engineering and the architecture of the agent using ADK 2.0.

Happy building!

Top comments (1)

Collapse
 
max_quimby profile image
Max Quimby

The scale-to-zero-kills-your-loop problem is the one that catches everyone the first time they try to run an agent as a "service." The note about avoiding SQLite on FUSE-mounted volumes is worth its weight — we learned that one the hard way when concurrent writes over a GCS mount produced a database that looked fine locally and was subtly corrupt in the cloud. The JSON/Markdown-file state suggestion works well for single-instance agents, but I'd flag the assumption hiding in it: the moment you have one always-on container you've also made that container a single point of failure with no crash-recovery story unless the loop is fully idempotent and checkpoints often. We ended up writing state as append-only events rather than mutable files precisely so a mid-loop crash-and-restart couldn't leave a half-written state file. For $5.70/month the always-on Cloud Run instance is a genuinely nice primitive though — curious how it behaves on instance restarts (deploys, underlying host moves): does the mounted storage survive cleanly and does your loop pick back up, or is there a cold-start gap you had to design around?