Claude Code vs Gemini: My Stateful Image Workflow A developer has built a stateful image generation workflow using Google's Gemini 3.1 Flash Lite Image model (NB2Lite) wrapped in an MCP server, enabling iterative edits without losing visual context. The setup leverages the Interactions API to maintain state via interaction IDs, allowing follow-up prompts like "add a neon sign" without re-describing the entire scene. The developer reports cutting prompt-tweaking time by about 60% by avoiding stateless "prompt and pray" methods. Claude Code vs Gemini: My Stateful Image Workflow The problem with most image gen is that it's basically goldfish memory. You ask for a cyberpunk kitchen, it gives you one. You ask to add a ramen sign, and suddenly the kitchen is gone, the lighting changed, and the "cyberpunk" vibe shifted to "generic 90s sci-fi." It's stateless misery. I've been using a setup that wraps gemini-3.1-flash-lite-image aka NB2Lite into an MCP /en/tags/mcp/ server to feed it into Google Antigravity. Unlike the usual "prompt and pray" method, this uses the Interactions API, which actually maintains state. You generate an image, get an interaction id , and then you can just say "add a neon sign" without re-describing the entire room. The Technical Plumbing The magic happens because the server handles the interaction id handoffs. If you're trying to build something similar, here is how the stateful loop actually functions: 1. Initial call: client.interactions.create prompt="...", store=True 2. Response: You get an interaction id . 3. Follow-up: You send the new prompt + previous interaction id . The server implementation I'm using via FastMCP basically abstracts this so the agent doesn't have to manage the IDs manually. Here is a snippet of how the tool definition looks in the server.py logic: Example of how the stateful edit is handled in the MCP server @mcp.tool async def edit image prompt: str, interaction id: str : """Edits an existing image using its interaction ID to maintain visual state.""" response = await client.interactions.create prompt=prompt, previous interaction id=interaction id, store=True return { "image url": response.url, "new interaction id": response.interaction id } Real-World Constraints The "Gotchas" Since I'm the one actually dogfooding this while my team asks "why isn't it perfect yet," here are the specific technical walls you'll hit: The Aspect Ratio Trap: You set the ratio 1:1 , 16:9 , etc. at the start. If you try to change it during a stateful edit, the pixel continuity falls apart. The server I'm using explicitly blocks aspect ratio changes during edits to prevent the model from hallucinating a new composition. Thinking Levels: The API documentation mentions minimal and medium thinking levels. In reality, if you send those to the flash-lite-image model, you get a crisp HTTP 400 error. Stick to low for fast drafts and high for when you actually need the text in the image to be readable. ID Forking: Every edit generates a new ID. If your agent accidentally references an ID from three turns ago, it doesn't error out—it just "forks" the image state back to that version, which is a nightmare to debug if you don't have logging enabled. Deployment Workflow For those who want to stop wasting time with stateless prompts, the deployment is straightforward. You need the nb2lite-skill-agy package, which acts as both the MCP server and the Antigravity skill definition. 1. Install the server dependencies. 2. Configure your Gemini /en/tags/gemini/ API key in the environment. 3. Link the MCP server to your Antigravity config. Once that's done, the workflow changes from "Write a 50-word prompt describing every detail" to "Change the color of that chair to red." It's significantly faster, and I've managed to cut my "prompt tweaking" time by about 60% because I'm not fighting the model to keep the background consistent. Next System Design: Mastering Back-of-the-Envelope Estimation → /en/threads/2801/