Deezwatts Agentic AI

Creative Mode Unblocked
Section titled “Creative Mode Unblocked”I spent 2024 giving this distraction a shot with aspirations of a high quality personal blog backed by technology, the outdoors, and the nerd within. Admittedly I spent more time in Club 429 with rate limiting than I did with the editor or the outdoors or even seeed studio orders. 2025 was confusing, and I wondered if I even ever wanted to create any type of content with the boom of Generative AI, at all, ever, even if I was moderately happy with what I was producing.
But now in 2026, my version of “yet another AI has changed my workflow story”, and a chance to have some fun with and re-boot a passive hobby with my truck, my Rivian R1S named Deezwatts and my Data Adventure with the same name.
The Epiphany
Section titled “The Epiphany”November of 2025, Antigravity was released by Google, and I immediately switched to it to reduce the noise and go all in on an AI first workflow. Having been fumbling through other IDEs, Zed, Cursor, and VSCode (which was suffering self inflicted bloat I could not seem to get out from under), so I gave in to Antigravity and started building with it purposefully as my guide.

It may seem strange to give this much credit to an IDE, but I am a strong believer that you dont go out and buy workflow tools, and then jam the same workflow from before into it. You have to let the tool shape the workflow, and in doing so, you end up having a ridiculous amount of fun building with it, and I rarely leave the IDE + Github as I did previously. I built a small MCP server to serve the stock price from Home Assistant to the IDE, and now I can query that as if it were a local database. This was straight forward to me, and MCP became important for things like MEMORY, but less impressive than employing the power of the Agency Roster, some excellent work by msitarzewski of github for the content.
Agency Agents
Section titled “Agency Agents”After cloning https://github.com/msitarzewski/agency-agents and taking a quick peak at the Agency Roster, you can see that all of the sudden I had a roster of agents to turn stalled projects into functioning ones that are a joy to iterate on. The Front End Developer I never was, the Content Writer I spin out pretending to be, the _________ I never was, the data engineer I fired, etc.
Agency Agents works with Claude out of the box, but to get it working with Antigravity (Gemini) I just needed to do the following, as each agent becomes a skill in ~/.gemini/antigravity/skills/agency-<slug>/, with these simple steps.
./scripts/convert.sh./scripts/install.sh --tool antigravityNaturally I went off the deep end and started building out a specific agent to generate “adventures” (and used an agent to do it)

Though cute, I really didnt need it, but it was a great excercise in agent building and prompt engineering and I retained it for output expectations. Instead, what I needed was an agency roster to help me get my act together, and understand a workflow for compounding the agents to a meaningful purpose and repeatable process.
| Agent | Role in Deezwatts |
|---|---|
| Frontend Developer | Modify the Astro app |
| Rapid Prototyper | Get the first version running fast |
| Technical Writer | Write the content with the right voice |
| Deezwatts | Output expectations |
Using the Agency roster, you just need to activate the agents in Gemini with Antigravity and prompt like a boss.
@agency-technical-writer show me how to create a Slack to NATS bridge so I can use it as messaging middleware for my Rivian adventures in Deezwatts and query information from the Rivian API, and then enrich the response using the ADK with Gemini. I am using python and will be deploying on Kubernetes. Also update the content in deezwatts-agentic-ai.md and use @agency-deezwatts for instructions on how to layout the content.
Professionally, I went through the evolution of chatting with models to putting them to work with tools, and eventually agents. The implementations seem to be all over the place, I found conversations on the what the best model was insanely false and empty, even with friends and I am searching for that “way” to standardize the way I implement agentic “thingers” into whatever the hell I am doing.
I went to an OpenClaw meetup with some friends and saw and it do its thing on a Mac Mini and was pretty amused and moderately impressed with the output, however, I didnt really get it, and an attempt to get it running on my own ended in never ever doing it again. Though the concept of a background job or many jobs completing tasks with formidable output is something I took away from it, and started my journey over with Google’s ADK.
So I stayed true and let the Google ecosystem show me the way, and I started with joining GEAR (Gemini Enterprise Agent Ready ) and completing these two courses.
Introduction to Agents and Google’s Agent Ecosystem
Develop Agents with Agent Development Kit (ADK)
Now, Im a Kubernetes person, so spinning up resources with a lifecycle, wither it be a distributed workload, a cronjob, a replica set, daemon set or a pod, it is second nature to run the ADK powered pods on Kubernetes and surround it with Cloud Native tooling for secrets, oidc, and have it all run on my own commodity hardware in my own homelab.
My “OpenClaw” ended up being ADK agents (or closely modeled), running as pods on Kubernetes… moreover for this project in particular, the agents have a one to one relationship with a NATS topic, and the agents are triggered by messages on that topic.
Here is a very simple example of an agent that listens to a NATS topic and publishes a response from the Rivian API and enriches it with Gemini back to the caller.
import osimport jsonimport asyncioimport natsimport google.generativeai as genaifrom rivian_python_api import Rivian
# --- 1. Rivian Token Management ---def get_authenticated_rivian(): with open("/data/rivian_tokens.json", "r") as f: data = json.load(f)
rivian = Rivian() # Using your underscore key rivian.create_session(data["_refreshToken"]) return rivian
def get_vehicle_info(): """Fetches the current battery level and range of the Rivian.""" # We define this as a regular 'def' because the library is sync # and Gemini handles standard function execution without warnings. rivian = get_authenticated_rivian()
vehicles = rivian.get_vehicles() v_id = vehicles[0]['vehicleId'] state = rivian.get_vehicle_state(v_id)
return { "soc": state['energyStorage']['soc']['value'], "range_miles": state['energyStorage']['distanceToEmpty']['value'], "charger_status": state['chargerState']['status']['value'] }
# --- 3. Gemini Configuration ---genai.configure(api_key=os.environ["GEMINI_API_KEY"])model = genai.GenerativeModel( model_name='gemini-2.5-flash', tools=[get_vehicle_info])
# --- 4. The NATS Handler ---async def message_handler(msg): subject = msg.subject reply = msg.reply data = msg.data.decode()
print(f"Received request on {subject}: {data} {reply}")
# Start a chat session with Function Calling enabled chat = model.start_chat(enable_automatic_function_calling=True)
try: # Gemini decides if it needs to call get_vehicle_info based on the prompt response = await chat.send_message_async(data)
# Send the final natural language answer back to the reply topic if reply: await nc.publish(reply, response.text.encode()) print(f"Replied with: {response.text}")
except Exception as e: error_msg = f"Error processing request: {str(e)}" print(error_msg) if reply: await nc.publish(reply, error_msg.encode())
# --- 5. Main Loop ---async def main(): global nc # Connect to NATS (Use the explicit IPv4 to avoid the timeout you saw) nats_url = os.getenv("NATS_URL", "nats://100.74.109.126:4222")
try: nc = await nats.connect(nats_url) print(f"Connected to NATS at {nats_url}")
# Subscribe to the topic (matches the one published by your Slack bot) await nc.subscribe("rivian.ai.prompt", cb=message_handler) print("Listening for Rivian AI prompts...")
# Keep the connection alive while True: await asyncio.sleep(1)
except Exception as e: print(f"NATS Connection Error: {e}")
if __name__ == "__main__": asyncio.run(main())So there it is, a simple agent that listens to a NATS topic and publishes a response from the Rivian API and enriches it with Gemini.
The tool is a function that is called by the agent, and the agent is called by NATS, and the publisher to NATS can be anything, a Slack bot, a Python script, a webhook, etc. All I have to do is ensure the Pod is running and has the right secrets, enough tokens on a Gemini key, the right environment variables, and the agent and I will get along just fine.