#!/usr/bin/env python """DIY Creator (#17 of the 30-in-15) — a multi-agent team you can watch work. A 🔍 Researcher, an ✍️ Writer, and a 🧐 Critic hand off to each other to produce a vetted build guide. The critic scores the draft and sends it back until it passes — a real critique->revise loop, shown live. The lesson is multi-agent orchestration: role-specialized agents, explicit handoffs, and an independent critic (the "diamond") gating the result. Each step is its own endpoint so the browser renders the team working in real time. pip install -r requirements.txt python app.py # http://127.0.0.1:7860 (local Ollama by default; ANTHROPIC_API_KEY for Claude) """ import os from flask import Flask, request, render_template_string, jsonify import agents import llm app = Flask(__name__) MAX_TOPIC = 160 PAGE = r""" GritAI · DIY Creator
GritAI · DIY Creator
A research → write → critique team that builds you a vetted guide
#17 · 30-in-15

Name something you want to build. A Researcher gathers the materials, tools and safety; a Writer drafts a step-by-step guide; then an independent Critic scores it and sends it back for revisions until it passes. You watch the whole team work.

Backend: {{ backend }} · max {{ max_rev }} critic rounds · GritAI Solutions

""" @app.route("/") def index(): return render_template_string(PAGE, backend=llm.backend_label(), max_rev=agents.MAX_REVISIONS) def _topic(): d = request.get_json(force=True, silent=True) or {} return (d.get("topic") or "").strip()[:MAX_TOPIC], d @app.route("/api/research", methods=["POST"]) def api_research(): topic, _ = _topic() if not topic: return jsonify({"error": "Tell me what you want to build."}) try: return jsonify({"brief": agents.research(topic)}) except Exception as e: print(f"research error: {type(e).__name__}") return jsonify({"error": "The researcher couldn't reach the model backend."}) @app.route("/api/write", methods=["POST"]) def api_write(): topic, d = _topic() brief = d.get("brief") or {} if not topic: return jsonify({"error": "Missing project."}) try: return jsonify({"guide": agents.write(topic, brief)}) except Exception as e: print(f"write error: {type(e).__name__}") return jsonify({"error": "The writer couldn't reach the model backend."}) @app.route("/api/critique", methods=["POST"]) def api_critique(): topic, d = _topic() brief, guide = d.get("brief") or {}, d.get("guide") or "" if not (topic and guide): return jsonify({"error": "Missing guide to review."}) try: return jsonify({"verdict": agents.critique(topic, brief, guide)}) except Exception as e: print(f"critique error: {type(e).__name__}") return jsonify({"error": "The critic couldn't reach the model backend."}) @app.route("/api/revise", methods=["POST"]) def api_revise(): topic, d = _topic() brief, guide, verdict = d.get("brief") or {}, d.get("guide") or "", d.get("verdict") or {} if not (topic and guide): return jsonify({"error": "Missing guide to revise."}) try: return jsonify({"guide": agents.revise(topic, brief, guide, verdict)}) except Exception as e: print(f"revise error: {type(e).__name__}") return jsonify({"error": "The writer couldn't reach the model backend."}) if __name__ == "__main__": port = int(os.environ.get("PORT", "7860")) app.run(host="0.0.0.0", port=port, debug=False)