{"slug": "how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you", "title": "How I Built an Adversarial AI Council in React (and Why It Argues With You)", "summary": "A developer built NoFlattery, a single-file React SPA that hosts a council of AI agents with different reasoning biases to debate user decisions. The app generates a Decision Record with a verdict, reasoning, risks, and next steps, and stores all data locally in the browser via IndexedDB. The project emphasizes local-first privacy, deterministic agent behavior, and simple deployment as a single HTML file.", "body_md": "A local-first, single-file SPA where multiple agents debate your decision and hand you a verdict.\n\nI almost named this project wrong.\n\nI'd picked a name that sounded powerful. I asked ChatGPT, and it loved it. I asked Claude, and it nodded along. Nobody warned me about the trademark conflict, the wrong search intent, or the SEO fight I'd pick with the BBC.\n\nThat was the moment I realized the problem wasn't the name. It was the feedback loop. Most AI assistants are tuned to please, so they hide your blind spots instead of showing them. When you need to make a consequential decision, \"sounds great\" is the most expensive answer you can get.\n\nSo I built the opposite: a council of AI agents that disagree on purpose.\n\nNoFlattery puts 2–4 agents in a room, gives them different reasoning biases, and makes them debate your decision. The output isn't another chat transcript. It's a Decision Record: a clear verdict, the reasoning behind it, the main risk, what would change the call, and a next step.\n\nUse it for product decisions, pricing, tech stack, hiring, or any call where one perspective isn't enough.\n\nKey product choices:\n\nThe whole app is a single-file SPA built with:\n\n`vite-plugin-singlefile`\n\nfor a single `index.html`\n\ndeployWhy single-file? Because the deploy becomes dead simple. One HTML file. No server for the data. No build orchestration. I can ship the app to Cloudflare Pages and forget about it.\n\nThe heart of NoFlattery is a turn-based multi-agent engine. One user message triggers one round. Each agent speaks in order, with a defined bias. There are no hidden selector models deciding who talks next. No silent fallbacks that break identity contracts.\n\nThe flow looks like this:\n\n`@mention`\n\neach other to force a direct response.Discussion modes are prompt injections, not separate state machines. Adversarial mode makes agents challenge harder. Audit mode makes them look for flaws. Vote mode forces a clear verdict. This keeps the runtime small and predictable.\n\nEvery conversation, every API key, every preference lives in IndexedDB via Dexie. Nothing leaves the browser unless you choose to call a provider with your own key.\n\nThis isn't a compromise. It's a feature. For a tool about honest decisions, the privacy model should match the message: your data is yours.\n\nThe only server touch is license validation for Pro. Even that is just a key plus a device hash. No chat history. No prompts. No telemetry.\n\n**1. Users don't want another chatbot.**\n\nThey want a decision they can defend. The transcript matters less than the verdict. That's why the Decision Record is the first-class output, not the chat.\n\n**2. Single-file deploy removes a lot of headache.**\n\nNo Docker. No DB migrations. No \"works on my machine.\" I run `npm run build`\n\nand get one `index.html`\n\n. The infrastructure complexity drops to near zero.\n\n**3. Local-first is a trust shortcut.**\n\nEspecially for early users who don't know you. \"Your data stays in your browser\" is easier to believe than \"we promise not to look.\"\n\n**4. Determinism matters more than cleverness.**\n\nI tried smarter routing. Hidden selectors. Model-based orchestration. Every time, the system became harder to debug and less trustworthy. One round, one order, one identity per agent. That's the constraint that makes the product feel reliable.\n\nIf you have a decision you'd run through a council:\n\nDrop the decision in the comments. I'm curious what a room of disagreeing agents would say about it.", "url": "https://wpnews.pro/news/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you", "canonical_source": "https://dev.to/stephen_dale_f411c38562bd/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you-4a2d", "published_at": "2026-06-19 06:20:43+00:00", "updated_at": "2026-06-19 06:30:00.918738+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools", "ai-agents", "ai-products", "large-language-models"], "entities": ["NoFlattery", "ChatGPT", "Claude", "Cloudflare Pages", "IndexedDB", "Dexie", "React", "Vite"], "alternates": {"html": "https://wpnews.pro/news/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you", "markdown": "https://wpnews.pro/news/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you.md", "text": "https://wpnews.pro/news/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you.txt", "jsonld": "https://wpnews.pro/news/how-i-built-an-adversarial-ai-council-in-react-and-why-it-argues-with-you.jsonld"}}