Blog #9: I Gave My Minecraft Mod a Serverless Brain — And It Decides How Many Allies to Summon Based on How Screwed You Are A developer has created a Minecraft mod that integrates a serverless AI agent to dynamically determine the number of allies summoned based on the player's combat situation. The mod, called Cloud Swords, uses AWS services like Lambda and DynamoDB to process combat context and return decisions, with a fallback rule-based system. The developer detailed the architecture, including API key authentication and a deployment timer, in a blog post. Cloud Swords Mod — Blog 9 I've been building a Minecraft mod that teaches cloud computing through gameplay. Swords named after AWS services. Energy systems that work like network infrastructure. Villagers that trade cloud certifications. But version 0.3.8 is where things got weird. I connected the mod to an actual AI agent running in the cloud. Now when you swing the Sword of Lambda, instead of spawning a fixed number of minions — an AI evaluates your combat situation and decides how many allies you need. The game never freezes. The AI never breaks balance. And the whole thing runs on a serverless backend that costs essentially nothing. Here's how I built it. Every cloud connection starts with authentication. In the mod, that's the Tome of API Key — a rare artifact found in dungeon chests 8% drop rate in bastions, end cities, nether fortresses . When you first pick it up, it generates a unique API key csk-XXXX format and shows 100 charges. It glows with enchant shimmer. It's your passport to the cloud. // On first inventory tick, generate unique key if stack.getNbt .contains "api key" { String key = "csk-" + UUID.randomUUID .toString .substring 0, 8 ; stack.getNbt .putString "api key", key ; stack.getNbt .putInt "charges", 100 ; } The tooltip shows your key preview, remaining charges, and connection status. When charges hit zero, the cloud refuses your invocations — just like hitting a rate limit on a real API. The Cloud API Requester is the bridge between Minecraft and AWS. It's a crafted block Iron + Circuit Board + Redstone + Ender Pearl + Data Core with two slots: Drop both in, wait ~8 seconds the "deployment timer" , and your weapon gets marked with cloud enabled=true in its NBT data. The tooltip now shows "☁ Cloud Enabled" in cyan. This is the CI/CD pipeline of the mod. You're deploying your weapon to the cloud. Once cloud-enabled, the Sword of Lambda changes behavior completely. Instead of spawning a hardcoded number of minions, it: If you're NOT cloud-enabled, the sword works exactly as before. Backward compatible. No cloud required. ┌─────────────────────────────────────────────────────────────┐ │ MINECRAFT CLIENT │ │ │ │ Player swings Sword of Lambda cloud-enabled │ │ │ │ │ ▼ │ │ CloudCombatHandler builds context: │ │ {player, weapon, health, biome, dimension, nearby mobs} │ │ │ │ │ ▼ │ │ CloudApiClient.sendEvent context ← async, non-blocking │ └───────┬─────────────────────────────────────────────────────┘ │ POST /event ▼ ┌─────────────────────────────────────────────────────────────┐ │ BACKEND CDK Stack │ │ │ │ API Gateway rate limited: 100/day, 10/sec │ │ │ │ │ ▼ │ │ Lambda: IngestEvent │ │ - Receives context │ │ - Calls Strands Agent or rule-based fallback │ │ - Stores decision in DynamoDB TTL: 60s │ │ - Returns {request id} │ │ │ │ DynamoDB: CloudSwordsResults │ │ - Partition key: request id │ │ - TTL auto-cleanup │ │ │ │ Lambda: PollResult │ │ - GET /result/{request id} │ │ - Returns decision when ready │ └───────┬─────────────────────────────────────────────────────┘ │ Poll every 2s ▼ ┌─────────────────────────────────────────────────────────────┐ │ CloudApiClient receives decision │ │ │ │ │ ▼ │ │ CloudCombatHandler.applyDecision │ │ - Summon "☁ Cloud Invocation" minions named, cyan │ │ - Or apply buff regeneration, resistance, strength │ │ - Or do nothing "No action needed" │ └─────────────────────────────────────────────────────────────┘ The game can NEVER freeze waiting for a network response. So I used the same pattern you'd use in any real-time application: request id immediately ServerTickEvents , check if the result is ready // CloudApiClient — non-blocking public void sendEvent JsonObject context { httpClient.sendAsync request, HttpResponse.BodyHandlers.ofString .thenAccept response - { String requestId = parseRequestId response.body ; startPolling requestId ; } ; } // Polling on server tick every 40 ticks = 2 seconds ServerTickEvents.END SERVER TICK.register server - { // Execute queued callbacks on server thread Runnable callback; while callback = pendingCallbacks.poll = null { callback.run ; } } ; The threading fix was critical. Java's HttpClient runs callbacks on its own async thread — but Minecraft entity spawning MUST happen on the server thread. Without the ConcurrentLinkedQueue bridge, buffs wouldn't apply and entities would crash the game. The brain is a Strands Agent running gpt-oss:20b via Ollama Cloud free tier — no Bedrock cost for development : python from strands import Agent from strands.models.ollama import OllamaModel SYSTEM PROMPT = """You are a combat advisor for a Minecraft RPG mod. Given player context, decide ONE action. Available actions respond ONLY with valid JSON : - {"action": "summon", "count": 1-5, "duration": 5-15, "reason": "brief"} - {"action": "buff", "effect": "regeneration|resistance|strength|speed", "duration": 3-10, "reason": "brief"} - {"action": "none", "reason": "brief"} Rules: - If health < 8 and many mobs: summon max allies or buff resistance - If health 15 and few mobs: action none or summon 1 - Scale response to threat level - ONLY output the JSON object, nothing else""" model = OllamaModel host="https://api.ollama.com", model id="gpt-oss:20b", agent = Agent model=model, system prompt=SYSTEM PROMPT The agent receives context like: { "player": "Carlos", "weapon": "sword of lambda", "health": 6, "nearby mobs": 8, "biome": "nether wastes", "dimension": "minecraft:the nether" } And responds: {"action": "summon", "count": 5, "duration": 10, "reason": "Critical threat"} The system prompt enforces bounded actions — the AI can't break game balance because it can only choose from a fixed set of actions with capped values. The production backend is a single CDK stack: python class CloudSwordsStack Stack : def init self, scope, id, kwargs : super . init scope, id, kwargs DynamoDB for async results results table = dynamodb.Table self, "DecisionResults", partition key={"name": "request id", "type": "STRING"}, time to live attribute="ttl", billing mode=dynamodb.BillingMode.PAY PER REQUEST, Lambda: receive event, decide, store ingest fn = lambda.Function self, "IngestEvent", runtime= lambda.Runtime.PYTHON 3 12, handler="handler.lambda handler", code= lambda.Code.from asset "lambda/ingest" , Lambda: poll result poll fn = lambda.Function self, "PollResult", runtime= lambda.Runtime.PYTHON 3 12, handler="handler.lambda handler", code= lambda.Code.from asset "lambda/poll" , API Gateway with usage plan rate limiting = gameplay mechanic api = apigw.RestApi self, "CloudSwordsApi" plan = api.add usage plan "Basic", throttle={"rate limit": 10, "burst limit": 20}, quota={"limit": 100, "period": apigw.Period.DAY}, The usage plan isn't just infrastructure — it's a gameplay mechanic. 100 requests per day means you can't spam the cloud. You have to be strategic about when you invoke it. Just like real API budgets. For development, I run a mock server that integrates the Strands Agent directly: mock server.py — localhost:8777 agent = None try: from combat advisor import create agent, decide agent = create agent print "✓ Strands Agent loaded" except: print "⚠ Agent unavailable, using rule-based fallback" def decide action body : if agent: return decide agent, body Fallback: simple rules if body "health" < 8 and body "nearby mobs" 5: return {"action": "summon", "count": 5, "duration": 10, "reason": "Critical"} return {"action": "summon", "count": 1, "duration": 5, "reason": "Standard"} The mock server logs every interaction to interactions.json — which becomes the eval dataset for Blog 10. | Game Mechanic | Cloud Concept | |---|---| | Tome of API Key | API keys + authentication | | 100 charges | Rate limiting / usage plans | | Cloud API Requester 8s timer | CI/CD deployment pipeline | cloud enabled=true NBT | Feature flags | | POST /event → request id | Async event processing | | Poll every 2s | Eventual consistency | | AI decides action | Serverless compute Lambda | | Bounded actions 1-5 minions | Guardrails / IAM boundaries | | CDK stack | Infrastructure as Code | | Mock server | Local development environment | Threading in Minecraft is brutal — anything touching entities must be on the server thread. Async HTTP + game logic = careful queue management. Rate limiting as gameplay works — players naturally strategize around limited cloud invocations. It teaches resource management without a lecture. AI guardrails through system prompts — bounding the action space 1-5 minions, specific buffs means the AI literally cannot break the game. The worst it can do is summon 5 minions when 3 would suffice. Fallback patterns matter — if the cloud is down, the sword still works with local logic. Graceful degradation, taught through a video game. The AI makes decisions. But are they good decisions? In Blog 10, I build an evaluation framework that judges the agent's combat advice — using another AI as the judge. Meta? Absolutely. Useful? Surprisingly yes. Code: I'm Carlos Cortez — cloud engineer, gamer, and apparently someone who connects Minecraft to AI agents for fun. This is Breaking the Cloud.