DEV Community

Cover image for Running a 24/7 Autonomous AI Agent on Google Cloud for $5.70/Month
Dzaki Amri Zaidaan
Dzaki Amri Zaidaan

Posted on Originally published at buildbyzaki.space

Running a 24/7 Autonomous AI Agent on Google Cloud for $5.70/Month

The Problem & Industry Shift

Autonomous AI agents are all the rage, but most tutorials assume you have unlimited cloud credits. Running a 24/7 agent that polls, processes, and acts can easily cost $50–$100/month if you naively spin up a VM. The industry is shifting toward serverless and event-driven architectures that scale to zero, but many developers still default to persistent compute. This article shows you how to run a production-grade autonomous agent on Google Cloud for just $5.70/month—the cost of a single e2-micro VM, but with better reliability and zero idle cost.

Architecture & Core Mechanics

The key is to avoid persistent compute. Instead, we use:

  • Cloud Scheduler to trigger the agent on a cron schedule (e.g., every 5 minutes).
  • Cloud Run to execute the agent logic as a stateless container that scales to zero.
  • Firestore as the durable state store, so the agent can pick up where it left off.
  • Cloud Tasks (optional) for retries and backoff.

The agent loop works like this:

  1. Cloud Scheduler fires an HTTP request to the Cloud Run service.
  2. The service loads the agent's state from Firestore.
  3. The agent performs its task (e.g., fetch data, call an LLM, make a decision).
  4. The new state is saved back to Firestore.
  5. The container exits, and you pay only for the compute time used.
+----------------+     HTTP     +----------------+     Read/Write     +-------------+
| Cloud Scheduler| -----------> |  Cloud Run     | <----------------> |  Firestore  |
| (cron)         |              |  (agent logic) |                    | (state)     |
+----------------+              +----------------+                    +-------------+
Enter fullscreen mode Exit fullscreen mode

This architecture is inherently serverless and scales to zero, meaning you pay only for the milliseconds of compute per invocation.

Production Code Example

Below is a minimal but production-ready agent in Python using FastAPI. It reads its state from Firestore, performs a simple task (e.g., fetching a quote from an API), and updates the state.

import os
import asyncio
from fastapi import FastAPI, HTTPException
from google.cloud import firestore
import httpx

app = FastAPI()

# Initialize Firestore client (uses GOOGLE_APPLICATION_CREDENTIALS)
db = firestore.AsyncClient()

# Agent configuration
AGENT_ID = os.getenv("AGENT_ID", "my-agent")
STATE_COLLECTION = "agent_state"

async def fetch_quote() -> str:
    """Fetch a random quote from an external API."""
    async with httpx.AsyncClient(timeout=5) as client:
        resp = await client.get("https://api.quotable.io/random")
        resp.raise_for_status()
        return resp.json()["content"]

async def run_agent_step(state: dict) -> dict:
    """Execute one step of the agent's logic."""
    # Example: fetch a quote and store it in the state
    quote = await fetch_quote()
    state.setdefault("quotes", []).append(quote)
    state["last_run"] = firestore.SERVER_TIMESTAMP
    return state

@app.post("/run")
async def run():
    """Entry point triggered by Cloud Scheduler."""
    doc_ref = db.collection(STATE_COLLECTION).document(AGENT_ID)
    doc = await doc_ref.get()
    state = doc.to_dict() if doc.exists else {}

    # Run the agent step
    try:
        new_state = await run_agent_step(state)
    except Exception as e:
        # Log and re-raise so Cloud Run returns 500 and Scheduler retries
        raise HTTPException(status_code=500, detail=str(e))

    # Save state back
    await doc_ref.set(new_state)
    return {"status": "ok", "state": new_state}

# For local testing
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)
Enter fullscreen mode Exit fullscreen mode

Key engineering decisions:

  • Statelessness: The container has no local state; all state is in Firestore. This allows Cloud Run to scale to zero and handle concurrent invocations safely.
  • Idempotency: The agent step should be idempotent. In this example, we append quotes, which could duplicate if retried. In production, you'd use a transaction or a unique ID.
  • Error handling: We catch exceptions and return 500 so Cloud Scheduler can retry with exponential backoff.
  • Timeout: The Cloud Run request timeout should be set to less than the Scheduler interval to avoid overlapping runs.

Performance, Cost & Trade-offs

Let's break down the cost for a 5-minute interval (288 invocations/day).

  • Cloud Run: 288 invocations × ~1 second CPU each = ~0.08 vCPU-seconds/day. Cloud Run's free tier includes 180,000 vCPU-seconds/month, so this is free. Even if you exceed, the cost is ~$0.000024/vCPU-second, so negligible.
  • Cloud Scheduler: 3 jobs are free, so 1 job is free.
  • Firestore: 288 reads + 288 writes per day = ~17k reads + 17k writes/month. Firestore's free tier includes 50k reads and 20k writes per day, so this is free. Even if you exceed, the cost is $0.06 per 100k reads and $0.18 per 100k writes.
  • Cloud Run always-on instances: If you set min-instances=1, you'd pay for a perpetual instance. At 0.5 vCPU and 256MB, that's ~$0.000023 per second × 2,592,000 seconds/month = ~$60/month. Avoid this. Keep min-instances=0.

So the total cost is $0.00 for this workload. But why $5.70? That's the cost of a single e2-micro VM on Compute Engine, which is a common alternative. If you need guaranteed low latency (no cold starts) or you want to run a heavier agent that requires more than 1 second of compute per step, you might opt for a VM. However, with Cloud Run you can increase the CPU allocation and still pay only for what you use.

Trade-offs:

  • Cold starts: Cloud Run may have a cold start of 1–2 seconds. If your agent must respond instantly, this could be a problem. Mitigation: use a minimum of 1 instance, but that costs ~$60/month.
  • Concurrency: Cloud Run can handle multiple invocations concurrently, but your agent must be designed to handle concurrent runs safely (e.g., using transactions).
  • State consistency: Firestore is eventually consistent, but for most agent use cases, this is fine. If you need strong consistency, consider using a transactional read-write.
  • External API rate limits: If your agent calls external APIs, you must handle rate limiting and backoff.

Actionable Checklist / Summary

To adopt this pattern in production:

  1. Design your agent as a stateless function that takes state as input and returns new state.
  2. Store state in Firestore (or any durable store) with a unique agent ID.
  3. Deploy as a Cloud Run service with --min-instances=0 and a request timeout less than your scheduler interval.
  4. Create a Cloud Scheduler job that hits your service's /run endpoint on your desired cron schedule.
  5. Set up error handling with retries (Cloud Scheduler retries on 500s by default).
  6. Monitor costs using the Google Cloud Console and set budgets.
  7. Test locally with the Firestore emulator.

References

Top comments (0)